1.9.17 支持异步安全重启特性
最后更新于:2022-04-02 06:17:43
# 1.9.17 支持异步安全重启特性
[TOC]
`1.9.17`版本重构了底层`WorkerStop`的机制,实现了异步安全重启的特性。包括`stop`、`reload`、`max_request`3个特性全部复用了一套代码。都支持了异步安全重启。
之前的版本 Worker进程收到`SIGTERM`、达到`max_request`时,会立即停止服务,这时`Worker`进程内可能仍然有事件监听,这些异步任务将会被丢弃。新版本中会先创建新的`Worker`,旧的`Worker`在完成所有事件之后自行退出。为了防止某些`Worker`一直不退出,底层还增加了一个`30`秒的定时器,在约定的时间内旧`Worker`没有退出,底层会强行终止。
> 可设置`server->max_wait_time`修改`Worker`进程最大等待时间,默认为`30`秒
## 实现原理
* `Worker`进程收到`SIGTERM`、达到`max_request`时,移除管道监听,立即回调`onWorkerStop`,并通知`Manager`进程。这时当前的`Worker`不会再收到任何客户端请求数据
* `Worker`进程会设置一个`30`秒的超时定时器,实现退出超时
* `Manager`进程收到`Worker`进程的消息后,创建新的`Worker`
* 新的`Worker`继续处理客户端请求数据
* 旧的`Worker`会持续触发`onWorkerExit`事件,`PHP`代码可以此事件回调函数中实现清理逻辑
* 旧的`Worker`会持续检测`EventLoop`中的`socket`数量,在没有任何事件监听后退出进程
* 旧的`Worker`在`30`秒内仍然没有完成异步`IO`任务,底层强制终止运行,退出进程
## 进程退出事件
为了支持异步重启特性,底层新增了一个`onWorkerExit`事件,当旧的`Worker`即将退出时,会持续触发`onWorkerExit`事件,在此事件回调函数中,应用层可以尝试清理某些长连接`Socket`
~~~
$serv->on('WorkerExit', function (swoole_server $serv, $worker_id) {
$redisState = $serv->redis->getState();
if ($redisState == Swoole\Redis::STATE_READY or $redisState == Swoole\Redis::STATE_SUBSCRIBE)
{
$serv->redis->close();
}
});
~~~
## 设置等待时间
~~~
$serv->set([
'max_wait_time' => 60,
]);
~~~
## 开启方式
onWorkerExit 回调功能需要设置`reload_async = true`才能开启
~~~
$serv->set(['reload_async' => true]);
~~~
';