六、Swoole 基础学习笔记 - 深入学习 Tcp Server 运行时参数配置
hi,我是温新,一名PHPer
文章基于 Swoole 5.0 版本编写。
学习目标:记住 Swoole Tcp 常用配置,了解其他相关配置
说明:本篇文章结合官方文档编写及参考网络资料编写,虽非全部原创,但也是结合了自己的理解,若转载请附带本文 URL,编写不易,持续编写更不易,谢谢!
上篇文章正式对是 Tcp Server 进行了一个记录,本篇文章将学习相关参数的配置。本篇文章将学习常用参数的配置,没有记录的参数请参考官方文档。
set 配置
max_conn
作用:服务器程序,最大允许的连接数(默认值为: ulimit -n
)。
如:max_conn => 1000
,设置 Server
最大允许维持 1000 个 TCP 连接。超过此数量后,新进入的连接将被拒绝。
max_conn
不允许设置太小,最设置的最小值为: (worker_num + task_worker_num) * 2 + 32
max_request
作用:设置 worker
进程的最大任务数。【默认值:0
即不会退出进程】。一个 worker
进程在处理完超过此数值的任务后将自动退出,进程退出后会释放所有内存和资源。
注意:此选项可以用于防止 worker 进程内存溢出。
演示:
<?php
$server->set([
'worker_num' => 2,
'reactor_num' => 3,
// 设置进程最大处理数
'max_request' => 2,
]);
配置好之后,使用另外一个客服端连接服务器,连接成功后向服务端发送数据,然后看看进程的变化:
# 客户端连接之前
$pstree -p 18001
php(18001)─┬─php(18002)─┬─php(18005)
│ └─php(18006)
├─{php}(18003)
└─{php}(18004)
# 客户端连接之后
$pstree -p 18001
php(18001)─┬─php(18002)─┬─php(18005)
│ └─php(18087)# 进程发生变化
├─{php}(18003)
└─{php}(18004)
task_worker_num
作用:配置 Task 进程数量。
注意:配置 task_worker_num 参数后,务必在 Server 中注册 onTask
、onFinish
事件回调。若没有注册,服务器程序将无法启动。
提示:
- Task进程是同步阻塞的;
- 最大值不得超过 swoole_cpu_num() * 1000;
-
计算方法
- 单个
task
的处理耗时,如100ms
,那一个进程 1 秒就可以处理1/0.1=10
个 task; -
task
投递的速度,如每秒产生2000
个task
; -
2000/10=200
,需要设置task_worker_num => 200
,启用200
个 Task 进程。
- 单个
演示:
<?php
// *** 省略
$server->set([
'worker_num' => 2,
'reactor_num' => 3,
'task_worker_num' => 2,
]);
// 监听异步任务
$server->on('Task', function($server, $taskId, $srcWorkerId, $data) {
});
// 监听异步任务完成
$server->on('Finish', function($server, $taskId, $data) {
});
// *** 省略
daemonize
作用:守护进程化【默认值:false
】。设置 daemonize => true
时,程序将转入后台作为守护进程运行。长时间运行的服务器端程序必须启用此项。如果不启用守护进程,当 ssh 终端退出后,程序将被终止运行。
提示:
- 启用守护进程后,标准输入和输出会被重定向到
log_file
; - 如果未设置
log_file
,将重定向到/dev/null
,所有打印屏幕的信息都会被丢弃; - 启用守护进程后,
CWD
(当前目录)环境变量的值会发生变更,相对路径的文件读写会出错。PHP
程序中必须使用绝对路径。
$server->set([
daemonize => true,
]);
方法
on
作用:用于注册 Server 的事件回调函数。
在之前的文章中见到它的次数很多了,监听某个事件回调就用它。要注意的是,重复调用同一个事件时,新的覆盖旧的,如下案例:
// 旧的
$server->on('Task', function($server, $taskId, $srcWorkerId, $data) {
});
// 新的
$server->on('Task', function($server, $taskId, $srcWorkerId, $data) {
});
start
作用:启动服务器,监听所有 TCP/UDP
端口。
reload
作用:安全地重启所有 Worker/Task 进程。
stop
作用:使当前 Worker
进程停止运行,并立即触发 onWorkerStop
回调函数。
shutdown
作用:关闭服务。
close
作用:关闭客户端连接。
send
作用:向客户端发送数据。
sendfile
发送文件到 TCP
客户端连接。
sendto
作用:向任意的客户端 IP:PORT
发送 UDP
数据包。
sendMessage
作用:向任意 worker 进程或 task 进程发送消息。在非主进程和管理进程中可调用。收到消息的进程会触发 onPipeMessage
事件。
exists
作用:检测 fd 对应的连接是否存在。
getClientInfo
作用:获取连接的客户端信息。
getClientList
作用:遍历当前 Server
所有的客户端连接,Server::getClientList
方法是基于共享内存的,不存在 IOWait
,遍历的速度很快。另外 getClientList
会返回所有 TCP
连接,而不仅仅是当前 Worker
进程的 TCP
连接。别名是 Swoole\Server->connection_list()
。
getWorkerId
作用:获取当前 Worker
进程 id
(非进程的 PID
)。
getWorkerPid
作用:获取当前 Worker
进程 PID
。
getWorkerStatus
作用:获取 Worker
进程状态。
getManagerPid
作用:获取当前服务的 Manager
进程 PID
。
getMasterPid
作用:获取当前服务的 Master
进程 PID
。
案例演示
使用 send 向客户端发送消息
<?php
$server = new Swoole\Server('0.0.0.0', 9501, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
$server->on('Receive', function ($server, $fd, $reactorId, $data) {
// 向客服端发送数据
$server->send($fd, 'Server:Hello ' . $fd . ' ,你发送的消息是: ' . $data) . PHP_EOL;
});
$server->start();
使用 sendFile 发送文件信息
<?php
$server = new Swoole\Server('0.0.0.0', 9501, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
$server->on('Receive', function ($server, $fd, $reactorId, $data) {
// 向客服端发送文件信息
$server->sendFile($fd, './message.txt');
});
$server->start();
属性
setting
作用:获取 set() 函数设置的所有参数。
演示:
<?php
// 其他的省略
$server->set([
'worker_num' => 2,
'reactor_num' => 3,
'task_worker_num' => 2,
]);
$server->on('Start', function($server) {
print_r($server->setting);
});
输出结果如下:
$php 3-swoole-tcp-param.php
Array
(
[worker_num] => 2
[reactor_num] => 3
[task_worker_num] => 2
[output_buffer_size] => 4294967295
[max_connection] => 1024
)
$master_pid
作用:返回当前服务器主进程的 PID
$manager_id
作用:返回当前服务器管理进程的 PID
$worker_id
作用:获取当前 Worker 进程的编号,包含 Task 进程
$worker_pid
作用:获取当前 Worker 进程的操作系统进程 ID。
$taskworker
作用:当前进程是否是 Task 进程。
返回值:boolean。true 表示当前进程是 Task 进程;false 表示当前进程是 Worker 进程。
$connections
作用:包含所有 TCP 连接
综合演示:
<?php
$server = new Swoole\Server('0.0.0.0', 9501, SWOOLE_PROCESS);
$server->set([
'worker_num' => 2,
'reactor_num' => 3,
'task_worker_num' => 2,
]);
$server->on('Connect', function ($server, $fd, $reactorId) {
echo $fd . ' 连接了' . PHP_EOL;
});
$server->on('Start', function($server) {
});
$server->on('Receive', function ($server, $fd, $fromId, $data) {
echo '主进程 ' . $server->master_pid . PHP_EOL;
echo '管理进程 ' . $server->manager_pid . PHP_EOL;
// 当前客户端连接的 Worker PID
echo 'workerPid 进程 ' . $server->worker_pid . PHP_EOL;
echo 'worker 进程 ' . $server->worker_id . PHP_EOL;
foreach ($server->connections as $fd) {
echo $fd . PHP_EOL;
}
});
$server->on('Workerstart', function ($server) {
if ($server->taskworker) {
echo 'task pid ' . $server->worker_pid . PHP_EOL;
} else {
echo 'worker pid' . $server->worker_pid . PHP_EOL;
}
});
// 监听异步任务
$server->on('Task', function($server, $taskId, $srcWorkerId, $data) {
});
// 监听异步任务完成
$server->on('Finish', function($server, $taskId, $data) {
});
$server->on('Close', function ($server,$fd) {
});
$server->start();
事件
onStart
作用:启动后在主进程(master)的主线程回调此函数。
onStart
回调中,仅允许echo
、打印Log
、修改进程名称。不得执行其他操作 (不能调用server
相关函数等操作,因为服务尚未就绪)。onWorkerStart
和onStart
回调是在不同进程中并行执行的,不存在先后顺序。
onWorkerStart
作用:此进程在 Worker 进程 / Task 进程启动时发生,这里创建的对象可以在进程生命周期内使用。
注意:onWorkerStart/onStart
是并发执行的,没有先后顺序。可以通过 taskworker
属性来判断是 worker 进程还是 task 进程。
onWorkerStop
作用:此事件在 Worker
进程终止时发生。在此函数中可以回收 Worker
进程申请的各类资源。
注意: 进程异常结束,如被强制 kill
、致命错误、core dump
时无法执行 onWorkerStop
回调函数。
onConnect
作用:有新的连接进入时,在 worker 进程中回调。
注意:onConnect/onClose
这 2
个回调发生在 Worker
进程内,而不是主进程。
onReceive
作用:接收到数据时回调此函数,发生在 worker
进程中。
onPacket
作用:接收到 UDP
数据包时回调此函数,发生在 worker
进程中。
UDP 服务中,只需要监听这一个事件即可。
onTask
作用:在 task 进程内被调用。worker 进程可以使用 task 函数向 task_worker 进程投递新的任务。当前的 task 进程在调用 onTask 回调时会将进程状态切换为忙碌,这时将不再接收新的 task,当 onTask 函数返回时会将进程状态切换为空闲然后继续接收新的 Task
。
onFinish
作用:此回调函数在 worker 进程被调用,当 worker
进程投递的任务在 task
进程中完成时,task 进程会通过 finish() 方法将任务处理的结果发送给 worker 进程。
onPipeMessage
作用:当工作进程收到由 $server->sendMessage()
发送的 unixSocket 消息时会触发 onPipeMessage 事件。worker/task进程都可能会触发
onPipeMessage` 事件
onWorkerError
作用:当 Worker/Task
进程发生异常后会在 Manager
进程内回调此函数。
onManagerStart
作用:当管理进程启动时触发此事件
onManagerStop
onBeforeReload
作用:Worker 进程 Reload
之前触发此事件,在 Manager 进程中回调
onAfterReload
作用:Worker 进程 Reload
之后触发此事件,在 Manager 进程中回调
onShutdown
作用:此事件在 Server
正常结束时发生
onBeforeShutdown
作用:此事件在 Server
正常结束前发生
演示:
修改进程名称
<?php
$server = new Swoole\Server('0.0.0.0', 9501, SWOOLE_PROCESS);
$server->set([
'worker_num' => 3,
'task_worker_num'=> 2,
]);
$server->on('Connect', function ($server, $fd) {
});
$server->on('Receive', function ($server, $fd, $reactorId, $data) {
});
// 设置 task 进程后,必须调用任务回调,不然会报错
$server->on('Task', function (Swoole\Server $server, Swoole\Server\Task $task) {
});
// 启动 master 进程时,设置进程名称
$server->on('Start', function ($server) {
swoole_set_process_name('swoole:master');
});
// 管理进程启动时,设置名称
$server->on('ManagerStart', function ($server) {
swoole_set_process_name('swoole:manager');
});
// worker 进程启动时,回调该事件,在这里我们对进程这是名称
$server->on('WorkerStart', function ($server, $workerId) {
if($workerId >= $server->setting['worker_num']) {
swoole_set_process_name("swoole:task worker");
} else {
swoole_set_process_name("swoole:php worker");
}
});
$server->on('Close', function ($server, $fd) {
});
$server->start();
进程之前发送消息
<?php
// 进程之间发送消息
$server = new Swoole\Server('0.0.0.0', 9501, SWOOLE_PROCESS);
$server->set([
'worker_num' => 5,
'reactor_num' => 3,
]);
$server->on('Receive', function ($server, $fd, $reactorId, $data) {
// 向其他进程发送消息
$server->sendMessage('hello', 1 - $server->worker_id);
});
// 监听管道,接收其他 进程发送的消息
$server->on('pipeMessage', function ($server, $srcWorkerId, $data) {
echo 'pipeMessage #' . $server->worker_id . ' message from #' . $srcWorkerId . $data . PHP_EOL;
});
$server->start();
输出结果:pipeMessage #1 message from #0hello
本篇文章至此就结束了,我是温新,我们下一篇文章见。