Swoole 关于reload重启与回调函数中代码的重载
Posted 神神的蜗牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swoole 关于reload重启与回调函数中代码的重载相关的知识,希望对你有一定的参考价值。
Swoole 的 Server 中可以通过 php 来执行 reload 很方便的热重载, 但也有很多限制
需要注意的是, 直接写在 server.php 即 你的服务器启动脚本文件中的PHP代码即便是写在 WorkerStart 的事件回调中的代码 reload 也不会重载的, 必须是通过加载另一个文件来执行这样 reload 才会有意义
下面是测试代码和结果说明:
<?php
/**
* Author: ZHOUZ
* Blog: http://blog.csdn.net/zhouzme
* Time: 2017-04-05 15:22
*/
function server()
{
$server = new Swoole\\Http\\Server("0.0.0.0", 9501);
/**
* 测试在 $server 外部注册全局自定义属性, 看看会不会被覆盖
*/
$server->myWorkerVar = 'global';
$server->set(array(
'worker_num' => 2,
'daemonize' => false,
));
// 服务器启动时执行一次
$server->on('Start', function (\\Swoole\\Http\\Server $server) {
echo PHP_EOL . PHP_EOL . 'Start: http://blog.csdn.net/zhouzme' . PHP_EOL . PHP_EOL;
});
// 服务器启动时执行一次
$server->on('ManagerStart', function (\\Swoole\\Http\\Server $server) {
echo 'ManagerStart: ' . PHP_EOL . PHP_EOL;
});
// 每个 Worker 进程启动或重启时都会执行
$server->on('WorkerStart', function (\\Swoole\\Http\\Server $server, int $workerId) {
// 通过重新加载外部文件来重载代码和释放之前占用的内存
//include_once __DIR__ . DIRECTORY_SEPARATOR .'workerstart.php';
// 下面这些直接写在当前文件中的代码即便重载也不会变化
echo 'WorkerStart: ' . PHP_EOL . PHP_EOL;
echo ' Worker ID: ' . $workerId . PHP_EOL . PHP_EOL;
// 启动服务器后, 去掉下面这行注释, 然后 reload , 该语句也不会执行的
//echo ' reloaded ! ' . PHP_EOL . PHP_EOL;
// 应该把这里的回调事件代码写在另一个文件中来 include 而不是直接写在这里
// 注意即便是 include_once , reload 也会重新加载的, 但在你的逻辑控制中是有效的
});
// 每次连接时(相当于每个浏览器第一次打开页面时)执行一次, reload 时连接不会断开, 也就不会再次触发该事件
$server->on('Connect', function (\\Swoole\\Http\\Server $server, int $fd, int $reactorThreadId) {
echo 'Connect: ' . PHP_EOL . PHP_EOL;
echo ' Worker ID: '. $server->worker_id . PHP_EOL . PHP_EOL;
echo ' fd: ' . $fd . ' , fromId: ' . $reactorThreadId . PHP_EOL . PHP_EOL;
});
// 浏览器连接服务器后, 页面上的每个请求均会执行一次,
// 每次打开链接页面默认都是接收两个请求, 一个是正常的数据请求, 一个 favicon.ico 的请求
$server->on('Request', function (\\Swoole\\Http\\Request $request, \\Swoole\\Http\\Response $response) use ($server) {
// 通过加载文件的方式来重载代码, 如果是 include_once 则只有第一次请求会加载, 其中的代码也只有第一次请求才会执行
include_once __DIR__ . DIRECTORY_SEPARATOR .'workerrequest.php';
// 下面所有的代码都应该放到另一个文件中, 否则 reload 无效, 你就只能 shutdown 再 start 了
// 下面这行去掉注释后 reload 也不会输出的
//echo ' ~~~~~ request reloaded ~~~~~ !';
if ($request->server['request_uri'] == '/favicon.ico') {
$response->end();
return;
}
echo 'Request: ' . PHP_EOL . PHP_EOL;
echo ' Worker ID: '. $server->worker_id . PHP_EOL . PHP_EOL;
echo ' URL: ' . ($request->server['request_uri'] ?? '') . PHP_EOL . PHP_EOL;
// 通过链接参数热重载 worker 进程观察触发事件
$act = $request->get['act'] ?? '';
if ($act == 'reload') {
echo ' ... Swoole Reloading ! ... ' . PHP_EOL . PHP_EOL;
// 触发 reload 之后, 貌似后面的代码也还是会执行的
$server->reload();
echo ' ... Under Reload ! ... ' . PHP_EOL . PHP_EOL; // 看看 reload 时是否会执行后续的代码
} elseif ($act == 'exit') {
// 直接立即终止当前 worker 进程, 和 reload 的效果比较相似, 新的 worker 进程的 ID 和原来的一样
// 所以程序内部应该尽量避免使用 exit 而应该抛出异常在外部 catch
echo ' ... Swoole Exit ! ... ' . PHP_EOL . PHP_EOL;
exit;
} elseif ($act == 'shutdown') {
// 直接立即终止当前 worker 进程, 和 reload 的效果比较相似, 新的 worker 进程的 ID 和原来的一样
// 所以程序内部应该尽量避免使用 exit 而应该抛出异常在外部 catch
echo ' ... Swoole Shutdown ! ... ' . PHP_EOL . PHP_EOL;
$server->shutdown();
echo ' ... After Swoole Shutdown ! ... ' . PHP_EOL . PHP_EOL;
}
$response->header("X-Server", "Swoole");
$msg = 'hello swoole !';
$response->end($msg);
});
$server->start();
}
server();
所有回调事件中的代码逻辑应该写在另一个文件中通过 include 来加载, 这样 reload 时才能平滑重启, 否则只能 shutdown server 再 start 了
WorkerStart 中 include 和 include_once 应该是没有区别的
Request 中 include_once 则只有第一次请求会加载并执行其中的代码, 之后的请求则会忽略加载也不会执行了, 但 reload 之后会重新加载文件并执行其中的代码
测试代码的输出结果:
Swoole 相关其他文章
以上是关于Swoole 关于reload重启与回调函数中代码的重载的主要内容,如果未能解决你的问题,请参考以下文章
Swoole 源码分析——Server模块之Worker事件循环