导读:此节将介绍所有的Swoole的回调函数,每个回调函数都是一个PHP函数,对应一个事件。onStart启动后在主进程(master)的主线程回调此函数function&nbs...
此节将介绍所有的 Swoole 的回调函数,每个回调函数都是一个 PHP 函数,对应一个事件。
启动后在主进程(master)的主线程回调此函数
function onStart(Swoole\Server $server);
参数
功能:Swoole\Server 对象
默认值:无
其它值:无
Swoole\Server $server
在此事件之前 Server
已进行了如下操作
接下来要执行
onStart
回调中,仅允许 echo
、打印 Log
、修改进程名称。不得执行其他操作 (不能调用 server
相关函数等操作,因为服务尚未就绪)。onWorkerStart
和 onStart
回调是在不同进程中并行执行的,不存在先后顺序。
可以在 onStart
回调中,将 $server->master_pid
和 $server->manager_pid
的值保存到一个文件中。这样可以编写脚本,向这两个 PID
发送信号来实现关闭和重启的操作。
onStart
事件在 Master
进程的主线程中被调用。
在 onStart
中创建的全局资源对象不能在 Worker
进程中被使用,因为发生 onStart
调用时,worker
进程已经创建好了
新创建的对象在主进程内,Worker
进程无法访问到此内存区域
因此全局对象创建的代码需要放置在 Server::start
之前,典型的例子是 Swoole\Table
在 onStart
回调中可以使用异步和协程的 API,但需要注意这可能会与 dispatch_func
和 package_length_func
存在冲突,请勿同时使用。
onStart
回调在 return
之前服务器程序不会接受任何客户端连接,因此可以安全地使用同步阻塞的函数。
SWOOLE_BASE 模式下没有 master
进程,因此不存在 onStart
事件,请不要在 BASE
模式中使用 onStart
回调函数。
WARNING swReactorProcess_start: The onStart event with SWOOLE_BASE is deprecated
此事件在 Server
正常结束前发生
Swoole 版本 >= v4.8.0
可用。在此事件中可以使用协程 API。
function onBeforeShutdown(Swoole\Server $server);
参数
功能:Swoole\Server 对象
默认值:无
其它值:无
Swoole\Server $server
此事件在 Server
正常结束时发生
function onShutdown(Swoole\Server $server);
参数
功能:Swoole\Server 对象
默认值:无
其它值:无
Swoole\Server $server
在此之前 Swoole\Server
已进行了如下操作
强制 kill
进程不会回调 onShutdown
,如 kill -9
需要使用 kill -15
来发送 SIGTERM
信号到主进程才能按照正常的流程终止
在命令行中使用 Ctrl+C
中断程序会立即停止,底层不会回调 onShutdown
注意事项
请勿在 onShutdown
中调用任何异步或协程相关 API
,触发 onShutdown
时底层已销毁了所有事件循环设施;
此时已经不存在协程环境,如果开发者需要使用协程相关 API
需要手动调用 Co\run
来创建协程容器。
此事件在 Worker 进程 / Task 进程 启动时发生,这里创建的对象可以在进程生命周期内使用。
function onWorkerStart(Swoole\Server $server, int $workerId);
参数
onWorkerStart/onStart
是并发执行的,没有先后顺序
可以通过 $server->taskworker
属性来判断当前是 Worker
进程还是 Task 进程
设置了 worker_num
和 task_worker_num
超过 1
时,每个进程都会触发一次 onWorkerStart
事件,可通过判断 $worker_id 区分不同的工作进程
由 worker
进程向 task
进程发送任务,task
进程处理完全部任务之后通过 onFinish 回调函数通知 worker
进程。例如,在后台操作向十万个用户群发通知邮件,操作完成后操作的状态显示为发送中,这时可以继续其他操作,等邮件群发完毕后,操作的状态自动改为已发送。
下面的示例用于为 Worker 进程 / Task 进程重命名。
$server->on('WorkerStart', function ($server, $worker_id){
global $argv;
if($worker_id >= $server->setting['worker_num']) {
swoole_set_process_name("php {$argv[0]} task worker");
} else {
swoole_set_process_name("php {$argv[0]} event worker");
}
});
如果想使用 Reload 机制实现代码重载入,必须在 onWorkerStart
中 require
你的业务文件,而不是在文件头部。在 onWorkerStart
调用之前已包含的文件,不会重新载入代码。
可以将公用的、不易变的 php 文件放置到 onWorkerStart
之前。这样虽然不能重载入代码,但所有 Worker
是共享的,不需要额外的内存来保存这些数据。onWorkerStart
之后的代码每个进程都需要在内存中保存一份
$worker_id
表示这个 Worker
进程的 ID
,范围参考 $worker_id
$worker_id 和进程 PID
没有任何关系,可使用 posix_getpid
函数获取 PID
协程支持
注意
发生致命错误或者代码中主动调用 exit
时,Worker/Task
进程会退出,管理进程会重新创建新的进程。这可能导致死循环,不停地创建销毁进程
此事件在 Worker
进程终止时发生。在此函数中可以回收 Worker
进程申请的各类资源。
function onWorkerStop(Swoole\Server $server, int $workerId);
仅在开启 reload_async 特性后有效。参见 如何正确的重启服务
function onWorkerExit(Swoole\Server $server, int $workerId);
有新的连接进入时,在 worker 进程中回调。
function onConnect(Swoole\Server $server, int $fd, int $reactorId);
接收到数据时回调此函数,发生在 worker
进程中。
function onReceive(Swoole\Server $server, int $fd, int $reactorId, string $data);
参数
关于 TCP
协议下包完整性,参考 TCP 数据包边界问题
例如:代码中可以增加一个 $buffer = array()
,使用 $fd
作为 key
,来保存上下文数据。 每次收到数据进行字符串拼接,$buffer[$fd] .= $data
,然后在判断 $buffer[$fd]
字符串是否为一个完整的数据包。
默认情况下,同一个 fd
会被分配到同一个 Worker
中,所以数据可以拼接起来。使用 dispatch_mode = 3 时,请求数据是抢占式的,同一个 fd
发来的数据可能会被分到不同的进程,所以无法使用上述的数据包拼接方法。
多端口监听,参考此节
当主服务器设置了协议后,额外监听的端口默认会继承主服务器的设置。需要显式调用 set
方法来重新设置端口的协议。
$server = new Swoole\Http\Server("127.0.0.1", 9501);
$port2 = $server->listen('127.0.0.1', 9502, SWOOLE_SOCK_TCP);
$port2->on('receive', function (Swoole\Server $server, $fd, $reactor_id, $data) {
echo "[#".$server->worker_id."]\tClient[$fd]: $data\n";
});
接收到 UDP
数据包时回调此函数,发生在 worker
进程中。
function onPacket(Swoole\Server $server, string $data, array $clientInfo);
TCP
客户端连接关闭后,在 Worker
进程中回调此函数。
function onClose(Swoole\Server $server, int $fd, int $reactorId);
在 task
进程内被调用。worker
进程可以使用 task 函数向 task_worker
进程投递新的任务。当前的 Task 进程在调用 onTask 回调函数时会将进程状态切换为忙碌,这时将不再接收新的 Task,当 onTask 函数返回时会将进程状态切换为空闲然后继续接收新的 Task
。
function onTask(Swoole\Server $server, int $task_id, int $src_worker_id, mixed $data);
参数
提示
$server->on('Task', function (Swoole\Server $server, Swoole\Server\Task $task) {
var_dump($task);
$task->finish([123, 'hello']); //完成任务,结束并返回数据
});
此回调函数在 worker 进程被调用,当 worker
进程投递的任务在 task
进程中完成时, task 进程会通过 Swoole\Server->finish()
方法将任务处理的结果发送给 worker
进程。
function onFinish(Swoole\Server $server, int $task_id, mixed $data)
当工作进程收到由 $server->sendMessage()
发送的 unixSocket 消息时会触发 onPipeMessage
事件。worker/task
进程都可能会触发 onPipeMessage
事件
function onPipeMessage(Swoole\Server $server, int $src_worker_id, mixed $message);
参数
功能:消息内容,可以是任意 PHP 类型
默认值:无
其它值:无
功能:消息来自哪个 Worker
进程
默认值:无
其它值:无
功能:Swoole\Server 对象
默认值:无
其它值:无
Swoole\Server $server
int $src_worker_id
mixed $message
当 Worker/Task
进程发生异常后会在 Manager
进程内回调此函数。
此函数主要用于报警和监控,一旦发现 Worker 进程异常退出,那么很有可能是遇到了致命错误或者进程 Core Dump。通过记录日志或者发送报警的信息来提示开发者进行相应的处理。
function onWorkerError(Swoole\Server $server, int $worker_id, int $worker_pid, int $exit_code, int $signal);
参数
功能:进程退出的信号
默认值:无
其它值:无
功能:退出的状态码,范围是 0~255
默认值:无
其它值:无
功能:异常 worker
进程的 pid
默认值:无
其它值:无
功能:异常 worker
进程的 id
默认值:无
其它值:无
功能:Swoole\Server 对象
默认值:无
其它值:无
Swoole\Server $server
int $worker_id
int $worker_pid
int $exit_code
int $signal
常见错误
signal = 11
:说明 Worker
进程发生了 segment fault
段错误,可能触发了底层的 BUG
,请收集 core dump
信息和 valgrind
内存检测日志,向 Swoole 开发组反馈此问题
exit_code = 255
:说明 Worker 进程发生了 Fatal Error
致命错误,请检查 PHP 的错误日志,找到存在问题的 PHP 代码,进行解决
signal = 9
:说明 Worker
被系统强行 Kill
,请检查是否有人为的 kill -9
操作,检查 dmesg
信息中是否存在 OOM(Out of memory)
如果存在 OOM
,分配了过大的内存。1. 检查 Server
的 setting
配置,是否 socket_buffer_size 等分配过大;2. 是否创建了非常大的 Swoole\Table 内存模块。
当管理进程启动时触发此事件
function onManagerStart(Swoole\Server $server);
提示
在 SWOOLE_BASE 模式下,如果设置了 worker_num
、max_request
、task_worker_num
参数,底层将创建 manager
进程来管理工作进程。因此会触发 onManagerStart
和 onManagerStop
事件回调。
Task
和 Worker
进程已创建
Master
进程状态不明,因为 Manager
与 Master
是并行的,onManagerStart
回调发生是不能确定 Master
进程是否已就绪
在这个回调函数中可以修改管理进程的名称。
在 4.2.12
以前的版本中 manager
进程中不能添加定时器,不能投递 task 任务、不能用协程。
在 4.2.12
或更高版本中 manager
进程可以使用基于信号实现的同步模式定时器
manager
进程中可以调用 sendMessage 接口向其他工作进程发送消息
启动顺序
BASE 模式
当管理进程结束时触发
function onManagerStop(Swoole\Server $server);
Worker 进程 Reload
之前触发此事件,在 Manager 进程中回调
function onBeforeReload(Swoole\Server $server);
参数
功能:Swoole\Server 对象
默认值:无
其它值:无
Swoole\Server $server
Worker 进程 Reload
之后触发此事件,在 Manager 进程中回调
function onAfterReload(Swoole\Server $server);
参数
功能:Swoole\Server 对象
默认值:无
其它值:无
Swoole\Server $server
所有事件回调均在 $server->start
后发生
服务器关闭程序终止时最后一次事件是 onShutdown
服务器启动成功后,onStart/onManagerStart/onWorkerStart
会在不同的进程内并发执行
onReceive/onConnect/onClose
在 Worker
进程中触发
Worker/Task
进程启动 / 结束时会分别调用一次 onWorkerStart/onWorkerStop
onTask 事件仅在 task 进程中发生
onFinish 事件仅在 worker
进程中发生
onStart/onManagerStart/onWorkerStart
3
个事件的执行顺序是不确定的
启用 event_object 后,以下事件回调将使用对象风格
$server->on('Connect', function (Swoole\Server $serv, Swoole\Server\Event $object) {
var_dump($object);
});
$server->on('Packet', function (Swoole\Server $serv, Swoole\Server\Packet $object) {
var_dump($object);
});
$server->on('PipeMessage', function (Swoole\Server $serv, Swoole\Server\PipeMessage $msg) {
var_dump($msg);
$object = $msg->data;
$serv->sendto($object->address, $object->port, $object->data, $object->server_socket);
});
$serv->on('WorkerError', function (Swoole\Server $serv, Swoole\Server\StatusInfo $info) {
var_dump($info);
});
$server->on('Task', function (Swoole\Server $serv, Swoole\Server\Task $task) {
var_dump($task);
});
$server->on('Finish', function (Swoole\Server $serv, Swoole\Server\TaskResult $result) {
var_dump($result);
});
本文地址:https://www.jinpeng.work/?id=72
若非特殊说明,文章均属本站原创,转载请注明原链接。