Coding Life

15 Sep 2019 Category:


layout: post title: 敲代码敲成老王了 category: php comments: true description: 我从小王开始敲代码,敲到现在成为老王了 keywords: PHP,就业选择,大公司小公司,BUG,需求变化 —

入坑代码行业

看着越来越高的发际线,我开始对着镜子会议自己是如何踏上代码这条不归路的。

我的专业是啥都学的”电子信息工程”,一个集硬件软件于一体,一听就高大上的专业。是的,我们要学电路,通信,c语言,微机原理,汇编语言,信号处理,图像处理,算了,太多了。

你说我们算是计算机专业么?你说算吧,我们又没有数据结构,算法相关的课程,对计算机的认识,估计就是知道word怎么操作的。

你说我们不算计算机专业么?又得知道计算机x86,arm芯片指令。

就在这样不明不白的专业中学习了四年,我们毕业了。大部分同学都成功转行到了软件测试行业。而我则利用我”专业的”51单片机技能成功在毕业之前找到一份实现工作,用”世界上最好的语言”做网站。如果不考虑大学学习的c语言,那么,PHP就是我的第一语言。

迷茫的探索

开始做网站,很大一部分工作都是调前端界面js,css之类的,php也是写一些业务CURD代码。那个年代,兼容浏览器真的会死人的,特别是对于我们这些搞PHP的人来说(你试试去兼容ie6看看)。当真正上手之后,开始怀疑”PHP真的是最好的语言”吗?

当时的行业场景,手机开发刚开始流行,于是开始转android开发,记得刚开始的时候还是android2.3,当自己真的在自己手机上跑起一个应用程序,那种感觉真的很好。但是随这时间的流逝(也没几个月),国内安卓版本开始越来越多。除了版本,还要兼容各种屏幕,品牌。突然感觉这和当时兼容浏览器有啥区别,又开始迷茫了。

手机应用的新起,另一个改变就是接口交互。后端的程序开发开始越来越单纯。你只需要考虑数据的正常返回就可以了,不用去考虑各种界面。似乎这才是自己所追求的。于是开始一头扎入后端的开发当中。

经过5年开发,目前在一家跨境电商公司任职PHP高级工程师。

自己变化

从业多年,回过头来看,还是有很大的变化。

从当年无知无畏到目前”畏手畏脚”。当初因为自己所学不多,基本上上手就是撸代码,无法全面的看到各个问题直接的关联性,在程序的设计上往往会有很大的欠缺,也会留下一些bug。而如今,基本上一个问题要考虑很多中异常,边界情况。对于这些异常情况都需要在开发之前找相关的责任人确认再开发(不确认,出了问题就得背锅)。

急躁不安到现在平平淡淡。程序员对于测试提的bug。反应无非就是三种: 1,什么,我的程序怎么会有bug,一定是你操作不对 2,哦,我看看 3,你描述一些操作场景(根据场景秒出解决方案)

我自己当年也是相信自己的程序没有bug的。但是慢慢的学会平淡接受了。虽然目前还没有办法给测试同学秒出解决方案。

对于需求的变更,真的很烦。刚开始入行的时候,我也在想,这些产品经理整体没屁事干,就动动嘴皮子,今天改这,明天改那。这个版本加的内容,下个版本删掉。后来才发现,要是没有他们,我们可不就失业了。再说了,老板是给工资的。再后来才发现,其实产品经理也不轻松。元素需求是要你做一个淘宝出来,产品经理要把这个”淘宝”的需求细化的解释给需求执行人员,同时协调好整个需求所需要的资源,最重要的是他们得背着那口那么大的锅。

当然,这还是取决于你遇到什么样的队友,这个行业不乏精英也不缺猪一样的队友。

对公司的看法

每到毕业的时候,总会有写人问是去大公司好还是去小公司好。这个真的得看情况。

如果你家里有矿,当然去小公司好。否则建议你去大公司。

我当时在小公司实习,后来有机会去大公司实习,确实大公司和小公司差别很大,和你心里所想的”大公司”差别也很大,于是我就”得瑟”的从大公司跑了。就这一步走错,我就把一副”王炸”的好牌打成世纪烂牌。

在大公司,需要你有造飞机的潜力又要你又拧螺丝的实力。也许你什么也学不会,但是你肯定会学会”待人”,另外你也肯定会自带大厂光环。

在小公司,你需要又九头六臂,还要抗压能力(不抗压,公司倒闭咋办),单身最好(单身狗好加班),离家近(晚上加班方便)。你能得到的有可能是你三年干倒六家公司的简历,有可能是三个月就黄了的项目经理,以及那0.1%的希望实现的大饼。

其实只要认清楚工作只是一份工作,选择就很好选择了。千万不要不自己的工作和自己的理想绑在一起。这只不过是一份自己干的得心应手,可以给老板带来利益,给自己带来生活收入的劳动力出卖交易而已。你的理想是你自己需要额外去实现,也只能你靠自己去实现。

好了,颠三倒四写了这么多。总结而言,对新入行的小伙伴以下几条建议

1、敲代码要认真,但是不要对工作出现的事情太认真,平淡对待

2、身体是自己的,理想是老板的,身体要紧

3、找工作不要相信谈理想的,不要被外表迷惑。要有自己的独立思考能力,拒绝被忽悠。遇到欠薪立马走,不要相信什么快发了的鬼话。

4、大公司可以镀金,能力提升靠自己,并不是小公司给你的,所以不要相信小公司能力提升快的鬼话

5、干这一行,你要学的精,又要学的广。

6、一入红尘深似海,发迹无边上头顶,照顾好自己的发际线

查看更多

Laraval Rate Limit

01 Aug 2019 Category:


layout: post title: Dingo Api 的限流在Laravel的限流基础上做了哪些修改? category: php comments: true description: Dingo Api 的限流在Laravel的限流基础上做了哪些修改 keywords: Dingo,Laravel,api限流 —

今天看文档的时候看到 Laravel的 节流限速 (throttling) 。网络上搜索,又看到了Dingo 的节流限速的文档。因此查看Laravel 与Dingo的源码,对比两者之间的相同点与不同点。

相同点

  • 两者都是通过中间件处理请求限流

  • 处理方式都是记录缓存key,设置过期时间,在没过期的时候自增,直到超出限制,或key过期

Laravel 限流中间件 Illuminate\Routing\Middleware\ThrottleRequests


public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1)
{
  $key = $this->resolveRequestSignature($request);

  $maxAttempts = $this->resolveMaxAttempts($request, $maxAttempts);

  if ($this->limiter->tooManyAttempts($key, $maxAttempts, $decayMinutes)) {
    throw $this->buildException($key, $maxAttempts);
  }

  $this->limiter->hit($key, $decayMinutes);

  $response = $next($request);

  return $this->addHeaders(
    $response, $maxAttempts,
    $this->calculateRemainingAttempts($key, $maxAttempts)
  );
}

Dingo 限流中间件Dingo\Api\Http\Middleware\RateLimit

public function handle($request, Closure $next)
{
  if ($request instanceof InternalRequest) {
    return $next($request);
  }

  $route = $this->router->getCurrentRoute();

  if ($route->hasThrottle()) {
    $this->handler->setThrottle($route->getThrottle());
  }

  $this->handler->rateLimitRequest($request, $route->getRateLimit(), $route->getRateLimitExpiration());

  if ($this->handler->exceededRateLimit()) {
    throw new RateLimitExceededException('You have exceeded your rate limit.', null, $this->getHeaders());
  }

  $response = $next($request);

  if ($this->handler->requestWasRateLimited()) {
    return $this->responseWithHeaders($response);
  }

  return $response;
}

不同点

  • 从上面两个中间件的代码可以看出,Laravel只有再没有超过限制的情况下才会对缓存进行+1操作,而Dingo是先操作再进行判断

  • Dingo 限制key以请求路径hash为前缀,默认以用户ip作为key。因此可以实现对用户每个url的限制,限制粒度更细

Dingo\Api\Http\RateLimit\Handler代码如下:

$this->keyPrefix = sha1($request->path());
...
public function getRateLimiter()
{
  return call_user_func($this->limiter ?: function ($container, $request) {
    return $request->getClientIp();
  }, $this->container, $this->request);
}

  • Laravel 中使用用户信息或域名+ip作为限制key,限制粒度只在用户级别

Illuminate\Routing\Middleware\ThrottleRequests代码如下:

  protected function resolveRequestSignature($request)
  {
    if ($user = $request->user()) {
      return sha1($user->getAuthIdentifier());
    }
    if ($route = $request->route()) {
      return sha1($route->getDomain().'|'.$request->ip());
    }
  }
  • Dingo支持修改限制key,Laravel默认没有支持修改方法

  • Dingo支持添加多个限制规则,逻辑上使用限制数最小的进行判断。因此假设有两个限制器,且都符合限制条件。一个限制1分钟10次,另一个限制2分钟15次,会使用1分钟1次的进行限制判断。

  • Dingo 返回了过期限制到期时间,Laravel默认不返回限制到期时间

Dingo\Api\Http\RateLimit\Handler获取限制最少的限制器代码如下:

public function rateLimitRequest(Request $request, $limit = 0, $expires = 0)
{
  ...
  $this->throttle = $this->getMatchingThrottles()->sort(function ($a, $b) {
        return $a->getLimit() < $b->getLimit();
      })->first();
  ...
}

Dingo\Api\Http\RateLimit\Handler获取设置的返回头信息代码如下:

protected function getHeaders()
{
  return [
    'X-RateLimit-Limit' => $this->handler->getThrottleLimit(),
    'X-RateLimit-Remaining' => $this->handler->getRemainingLimit(),
    'X-RateLimit-Reset' => $this->handler->getRateLimitReset(),
  ];
}

Illuminate\Routing\Middleware\ThrottleRequests获取设置的返回头信息代码如下:


protected function getHeaders($maxAttempts, $remainingAttempts, $retryAfter = null)
{
  $headers = [
    'X-RateLimit-Limit' => $maxAttempts,
    'X-RateLimit-Remaining' => $remainingAttempts,
  ];

  if (! is_null($retryAfter)) {
    $headers['Retry-After'] = $retryAfter;
    $headers['X-RateLimit-Reset'] = $this->availableAt($retryAfter);
  }

  return $headers;
}

总结

两者实现原理相同,只是在细节上Dingo的功能更加强大。Dingo 限制粒度系,限制规则上,可扩展性,灵活性都比Laravel强。

查看更多

Laraval Before Response

31 Jul 2019 Category:


layout: post title: Laravel 如何完成beforeResponse功能? category: php comments: true description: 关于 select 返回数据的顺序的几个问题 keywords: MYSQL,SELECT,分组第一条,TOP1 —

背景

一般的项目需求都会要求统一的输出结构,特别是对于api应用而言。因此,如果有beforeResponse的功能,则可以在数据输出之前对response进行统一格式化处理。

假设这么一种场景,应用做api开发,使用抛异常的方式(自定义异常类ApiException)返回无效非法请求的情况。正常请求则返回合法数据(数组或可序列化的模型),希望返回的数据格式

查看更多

关于 select 返回数据的顺序的几个问题

09 Jul 2019 Category: php

关于 select 返回数据的顺序的几个问题

数据内容如下:

id    page_id        addtime
1       1           1558342663
2       1           1558348337
3       1           1558349079
4       2           1558348351
5       4           1558348372
6       3           1558348361
7       1           1558349140
8       1           1558399247
9       3           1558349702
10      1           1558399412
11      1           1558402590
12      1           1558408852

1) 对select的结果没有任何条件进行select,顺序是怎么样?

查看更多

不知不觉踩到PHP内存泄漏的雷

27 Jun 2019 Category: php

最近工作上需要排查php频繁达到内存限制进程被杀掉的原因。项目中使用php写一个死循环,把mysql的数据同步到mq或者mongodb当中。内存问题主要出现在mq消息的发布上。项目中有使用到php-amqplib。

跟踪代码发现,循环内部,获取mq单例对象有问题导致每次循环都是new的一个mq对象。刚开始以为是这个原因导致内存不断增长。三下五除二就改完了,结果一试,没什么效果,还是不断飙升啊。

既然不是新对象引起的,那估计就是就对象的问题。因为新建对象都没有对已有的mq对象进行处理,例如端口连接,释放资源等。因此在新建对象之前,执行php-amqplib 中connection的close操作,关闭连接以及释放资源。关闭之后再操作,确实有些改变,飚的慢点,但是还是会飚。然后又在循环结束的时候unset对象,结果依然没什么变化。

查看更多

Laravel 5.8关于数组的小彩蛋

19 May 2019 Category: php

今天看Laravel5.8代码的时候,看到几个小彩蛋。

1、获取关联数组中指定部分键值组成的数组

项目中常常有这么一种场景,一些数据的生成需要一些其他的数据获得,但是返回给用户的不需要原始数据。比如对于一个用户数据如下:

{
    "userid":10,
    "username":"abc",
    "type":1,
    "status":1,
    "system_code":"xtfy",
    "system_uid":1,
    "file_id":1
}

如果我最终想要返回给用户的结果如下

{
    "userid":10,
    "username":"abc",
    "type":1,
    "status":1
}

这种情况就需要获取数组中指定的部分内容。实现方式有一下几种方式:

  • unset不需要的数据字段
  • 重新创建一个变量,然后一个个字段的添加到新数组中去

查看更多

web 开发会用到的linux命令

07 Mar 2019 Category: php

作为web开发,难免和服务器打交道。这里整理一下工作上会用到的命令。

1、获取服务器类型 很多情况下,由于历史遗留因素,给到你的服务器信息都只是一个访问ip,用户名,密码,其他什么都没了。所以登录到服务器上,一开始先要确定的是这台服务器是什么系统,什么版本。

查看更多

PHP 关于数组排序的函数

06 Mar 2019 Category: php

php的数组排序函数有很多。有按键排序,有按值排序。有升序,有降序。有的排序后改变原数组索引,有的不改变。

关于PHP的排序函数,官方文档给出了下面的一个总结表:

php array sort functions

以上函数排序结果都是通过引用传递到原数组中去,而不是返回一个新的有序的数组。

查看更多