swoole 5 中监听 sigusr1 实现自定义重载,需在 master 进程中注册信号、禁用默认 reload 行为(设置 reload_async=false 和 reload_type=swoole_reload_manual),回调中避免阻塞与协程 api,推荐异步加载配置或投递 task 处理耗时操作,并加 try/catch 防异常退出。

在 Swoole 5 中,监听 SIGUSR1 信号实现自定义重载逻辑,核心是让 Master 进程捕获该信号后不走默认 reload 流程,而是执行你自己的初始化、资源清理或配置刷新动作。这需要绕过 Swoole 内置的自动 Worker 重启行为,改用手动控制流程。
明确信号监听位置:只在 Master 进程注册
SIGUSR1 是用户自定义信号,Swoole 默认用它触发 Worker 平滑重启($server->reload()),但这个行为仅对 Master 进程有效。因此,必须确保信号注册代码只在 Master 进程中执行,否则子进程也会响应,造成混乱。
- 使用
if ($server->master_pid === posix_getpid())判断当前是否为 Master 进程 - 调用
Swoole\Process::signal(SIGUSR1, $callback)注册回调,注意该方法在 Swoole 5 中仍可用且推荐 - 避免在 Worker 或 Task 进程中重复注册,否则可能触发多次无效处理
禁用默认 reload 行为,接管控制权
Swoole 5 默认收到 SIGUSR1 会自动调用内部 reload(),若你希望执行自定义逻辑(如重载配置、刷新缓存、切换日志文件),需先关闭该默认行为:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 启动服务时设置
'reload_async' => false和'reload_type' => SWOOLE_RELOAD_MANUAL,防止自动触发 - 在信号回调中,**不要调用
$server->reload()**,而是执行你的业务逻辑 - 如需重启 Worker,可手动调用
$server->reload()或更精细地用$server->reloadWorker($worker_id)控制单个进程
编写安全的自定义重载回调
信号回调函数必须轻量、非阻塞、不可调用协程 API(如 co::sleep)或同步 I/O(如 file_get_contents)。推荐将耗时操作转为异步任务或投递到 task 进程处理:
- 读取新配置可使用
swoole_async_readfile()避免阻塞 - 刷新 Redis 缓存建议通过
$server->task()异步执行,防止阻塞事件循环 - 记录日志推荐用
Swoole\Logger或 PSR-3 兼容 logger,避免echo/var_dump - 示例片段:
Swoole\Process::signal(SIGUSR1, function () use ($server) {
go(function () use ($server) {
// 异步加载新配置
swoole_async_readfile(__DIR__ . '/config.php', function ($filename, $content) use ($server) {
Config::load(json_decode($content, true));
$server->task(['action' => 'clear_cache']);
});
});
});
验证与调试技巧
实际部署前务必验证信号是否被正确接收和处理:
- 启动服务后,用
kill -USR1 $(cat runtime/swoole.pid)手动触发,观察日志输出 - 检查
strace -p $(cat runtime/swoole.pid) -e trace=rt_sigaction,kill确认信号注册和接收过程 - 在回调中加入
file_put_contents('/tmp/sigusr1.log', date('Y-m-d H:i:s') . "\n", FILE_APPEND);做最简日志追踪 - 注意:Swoole 5 的信号处理更严格,若回调抛出未捕获异常,可能导致 Master 进程退出,建议加
try/catch










