共计 1910 个字符,预计需要花费 5 分钟才能阅读完成。
简单探究一下 swoole 的热重启问题
官方说是可以平滑重启所有的 worker 和 tasker 进程,可以通过
$swoole->reload(),或者 \swoole_process::kill($master_pid, SIGUSR1),或者直接 kill -USR1 master_pid 等等。
那我们来简单测试下,swoole 究竟是否能够平滑重启。
简单测试
开启一个 swoole_http_server,worker 进程和 tasker 进程都为 1 个,然后浏览器发起一个 http 请求,请求的内容只是简单的 sleep 一下,通过 sleep 函数,应该是可以说明处理此请求的 worker,是正在处于工作状态的吧,然后在 sleep 期间,进行 reload 操作。
当第一次发起一个请求到 swoole server,manager 进程会将请求调度到 worker 去进行处理,然后在 worker 处理的 sleep 期间,如果再有请求进来,manager 是不会将后续的请求调度给唯一的 worker 进程,因为 worker 进程还在忙碌处理第一个请求。这个可以通过简单测试确认。
http 请求就是路由到下面的简单方法。因为用的是 easyswoole 框架,执行 php easyswoole reload all 命令,其实也就是 kill -USR1 master_pid。
Server 的配置
$swoole_server->set([
'worker_num' => 1,
'task_worker_num' => 1,
'reload_async' => true,
'max_wait_time' => 5,
]);
开始测试
1、任务逻辑写在 worker 进程里面
http 方法
public function test()
{$start = microtime(true);
echo '请求开始时间:' . $start . PHP_EOL;
echo 'pid:' . getmypid() . PHP_EOL;
sleep(30); # 这里睡眠脚本作测试
echo 'finish sleep' . PHP_EOL;
$end = microtime(true);
echo '请求结束时间:' . $end . PHP_EOL;
$this->writeJson(0, round(($end - $start), 3));
}
监控 onWorkerStart() 方法
EventHelper::registerWithAdd(ServerManager::getInstance()->getMainEventRegister(),EventRegister::onWorkerStart,function (\swoole_server $server,$workerId){if(PHP_OS != 'Darwin'){$name = Config::getInstance()->getConf('SERVER_NAME');
if(($workerId < Config::getInstance()->getConf('MAIN_SERVER.SETTING.worker_num')) && $workerId >= 0){$type = 'Worker';}else{$type = 'TaskWorker';}
cli_set_process_title("{$name}.{$type}.{$workerId}");
}
# 下面是打印测试的
if ($type == 'Worker') {echo "这个是 reload worker 的时间:" . microtime(true) . "\n";
}
if ($type == 'TaskWorker') {echo "这个是 reload TaskWorker 的时间:" . microtime(true) . "\n";
}
});
测试结果:
请求开始时间:1566880257.9533 # 这里请求 http 接口,就是 test()
pid: 42108
这个是 reload TaskWorker 的时间:1566880265.1501 # 这里是执行 php easyswoole reload all 的时间,因为 tasker 空闲没任务,就马上就行 reload 了。这个是 reload worker 的时间:1566880275.1524 # 这个是 worker 的 reload 时间,因为在 test() 里面 sleep(30),而且超过了 max_wait_time,底层不会继续等待 worker 的任务完成,直接把旧的 worker 结束掉,结果也没有打印 'finish sleep',创建了新的 worker。# 但是为什么是 10s 才重新创建 worker 呢?max_wait_time 设置为 5s 啊??这个是我一直想不明白的。
有大神能够解析一下吗??困扰有点久了。
正文完