PHP 实现平滑关闭/重启
写过 CLI 常驻进程的老司机肯定遇到过这么一个问题:在需要更新程序的时候,我要怎样才能安全关闭老进程?你可能会想到 NGINX
、php-fpm
之类的平滑重启是给进程发送 USR2
信号,然后它就会将当前请求处理完再退出。
但进程是怎样接收信号、处理信号,估计就不是很多人能说清楚了。
写过 CLI 常驻进程的老司机肯定遇到过这么一个问题:在需要更新程序的时候,我要怎样才能安全关闭老进程?你可能会想到 NGINX
、php-fpm
之类的平滑重启是给进程发送 USR2
信号,然后它就会将当前请求处理完再退出。
但进程是怎样接收信号、处理信号,估计就不是很多人能说清楚了。
写 PHP CLI 程序的老司机们可能经常会写一些常驻进程,比如消息队列消费者进程,这些进程会一直运行,除非要发版,不然一般不会重启的,所以程序程序是不可能由我们通过 ssh 登录到服务器上通过终端来直接启动的(因为一旦断开 ssh 进程就退出了),常见的做法就是用 systemd
或者 supervisor
来使其成为 守护进程
,这样进程就可以一直运行,遇到错误意外退出也能被自动重启。
好学的你可能会思考守护进程到底是怎么实现的?为什么有的程序既可以自己就成为守护进程,又可以通过 systemd
来后台运行?如果不依赖外部,我们的 PHP 程序该怎样变成守护进程呢?
最近看到 GitHub 上有个仓库叫《牙医教你 450 行代码自制编程语言》,研究了一番,感觉很有意思,于是尝试用 PHP 去实现了一个简单的编程语言(PINEAPPLE lang)解释器,也算是对编译原理入了门😅
https://github.com/YianAndCode/pineapple-php
最近在写 Phalcon ORM 查询结果集遍历的时候发现 Phalcon ORM 有个很神奇的现象:当你用 foreach 遍历 Model->find() 之后的结果(Phalcon\Mvc\Model\Resultset\Simple
),如果在遍历中有访问下一个($key + 1)元素,就会自动执行 next(),下一个元素就不会出现在 foreach
的下一次遍历中了...
举个例子,比如说我们有一张表 users
,我们创建一个 User
model,执行如下代码:
<?php
$users = \Models\User::find([
'conditions' => 'role = 1' // 这里可以是别的查询条件
]);
// 这里假设查询出来的记录只有两条,即 count($users) == 2
foreach ($users as $key => $user) {
echo "key: $key, user_id: {$user->id}\n";
// 假设这里因为业务逻辑的需要访问下一个 model
$foo = $users[$key + 1];
}
你可能会觉得上面的循环在执行到第二次会报 PHP Notice: Undefined offset
,但实际上,它什么也没报,只是安安静静地输出了:
最近用了阿里云消息服务中的主题订阅,发现当 MNS 向 Endpoint 投递消息时,当前的签名机制会存在一定的风险
MNS Endpoint 的签名机制是使用 sha1WithRSAEncryption
对一系列参数签名,Enpoint 接收到请求之后再从 header 里取出相应的参数并校验其签名。
其中 sha1WithRSAEncryption
算法就会用到一张 X509 证书,这个是本次实验的关键。
在 PHP 里,如果想获取下个月的今天,我们通常会用 strtotime('2019-01-13 +1 month')
或者是 strtotime('next month', strtotime('2019-01-13'))
,结果是 1549987200
,用 date
转换成字符串就是 2019-02-13
,so easy!
随着时间流逝,到了 2019-01-31
这一天,这代码似乎出问题了,居然得到的是 2019-03-03
???