× 警告!旧版文档已经暂停维护,请查看新版文档。点击前往新版文档

Server->reload

安全地重启所有Worker/Task进程。例如:一台繁忙的后端服务器随时都在处理请求,如果管理员通过kill进程方式来终止/重启服务器程序,可能导致刚好代码执行到一半终止。这种情况下会产生数据的不一致。如交易系统中,支付逻辑的下一段是发货,假设在支付逻辑之后进程被终止了。会导致用户支付了货币,但并没有发货,后果非常严重。

底层提供了柔性终止/重启的机制,ServerWorkerTask进程可以安全的重启和终止。

函数原型

bool Server->reload(bool $only_reload_taskworkrer = false)
  • $only_reload_taskworkrer 是否仅重启Task进程
  • reload有保护机制,当一次reload正在进行时,收到新的重启信号会丢弃
  • 如果设置了user/groupWorker进程可能没有权限向Master进程发送信息,这种情况下必须使用root账户,在shell中执行kill指令进行重启
  • reload指令对addProcess添加的用户进程无效

平滑重启只对onWorkerStartonReceive等在Worker进程中include/requirePHP文件有效,Server启动前就已经include/requirePHP文件,不能通过平滑重启重新加载
对于Server的配置即$serv->set()中传入的参数设置,必须关闭/重启整个Server才可以重新加载
Server可以监听一个内网端口,然后可以接收远程的控制命令,去重启所有Worker进程

发送信号

  • SIGTERM: 向主进程/管理进程发送此信号服务器将安全终止
  • PHP代码中可以调用$serv->shutdown()完成此操作
  • SIGUSR1: 向主进程/管理进程发送SIGUSR1信号,将平稳地重启所有Worker进程
  • SIGUSR2: 向主进程/管理进程发送SIGUSR2信号,将平稳地重启所有Task进程
#重启所有进程
kill -USR1 主进程PID

#仅重启task进程
kill -USR2 主进程PID

Process 模式

Process模式下,来自客户端的TCP连接是在Master进程内维持的,worker进程的重启和异常退出,不会影响连接本身。

Base 模式

Base模式下,客户端连接直接维持在Worker进程中,因此reload时会切断所有连接。

Base模式不支持reload Task进程

Reload有效范围

Reload操作只能重新载入Worker进程启动后加载的PHP文件,建议使用get_included_files函数来列出哪些文件是在WorkerStart之前就加载的PHP文件,在此列表中的PHP文件,即使进行了reload操作也无法重新载入。比如要关闭服务器重新启动才能生效。

$serv->on('WorkerStart', function($serv, $workerId) {
    var_dump(get_included_files()); //此数组中的文件表示进程启动前就加载了,所以无法reload
});

APC/OpCache

如果PHP开启了APC/OpCachereload重载入时会受到影响,有2种解决方案

  • 打开APC/OpCachestat检测,如果发现文件更新APC/OpCache会自动更新OpCode
  • onWorkerStart中执行apc_clear_cacheopcache_reset刷新OpCode缓存

参考


  • 本物秣马儿

    http://group.swoole.com/question/105859 韩老师您好,在论坛上您说是向主进程发送usr1信号,但本文是SIGUSR1: 向管理进程发送SIGUSR1信号。请问哪个对?

  • Young

    发送usr1信号给master进程或者manager进程都可以达到目的; 发送给master进程的user1信号 会通过kill(SwooleGS->manager_pid, sig)再次发送给manager进程;

  • Young

    这贴不了代码,列一下仅供参考 Server.c 591行 swServer_signal_init();//初始化信号处理函数 Server.c 910行 swSignal_add(SIGUSR1, swServer_signal_hanlder);//添加信号处理函数 Server.c 1166行 kill(SwooleGS->manager_pid, sig);//发送信号给manager进程

  • lovejocky

    子进程怎么重启啊?

  • mango_alex

    发送信号给master进程或者manager进程,问题是怎么确定哪个是master进程,哪个是manager进程?

  • 秃子

    首先你知道自己监听的端口是哪一个,比如我监听的端口为9501 然后我用命令(sudo lsof -i tcp:9501)我这个是mac系统,然后可以列出这个端口下哪个进程在运行,然后再发送信号kill -USR1 主进程PID

  • 浅忆︿梦已凉”

    swoole_websocket_server 没有reload()吗

  • Listen

    $serv->set()配置发生更改必须重启服务才能生效嘛