Swoole常用配置

reactor_num

设置启动的 Reactor 线程数。【默认值:CPU 核数】。

通过此参数来调节主进程内事件处理线程的数量,以充分利用多核。默认会启用 CPU 核数相同的数量。
Reactor 线程是可以利用多核,如:机器有 128 核,那么底层会启动 128 线程。
每个线程能都会维持一个 EventLoop。线程之间是无锁的,指令可以被 128CPU 并行执行。
考虑到操作系统调度存在一定程度的性能损失,可以设置为 CPU 核数 * 2,以便最大化利用 CPU 的每一个核。

  • 提示
    • reactor_num 建议设置为 CPU 核数的 1-4
    • reactor_num 最大不得超过 swoole_cpu_num() * 4
  • 注意

reactor_num 必须小于或等于 worker_num
如果设置的 reactor_num 大于 worker_num,会自动调整使 reactor_num 等于 worker_num
在超过 8 核的机器上 reactor_num 默认设置为 8

worker_num

设置启动的 **Worker** 进程数。【默认值:CPU 核数】

1 个请求耗时 100ms,要提供 1000QPS 的处理能力,那必须配置 100 个进程或更多。
但开的进程越多,占用的内存就会大大增加,而且进程间切换的开销就会越来越大。所以这里适当即可。不要配置过大。

  • 提示
    • 如果业务代码是全异步 IO 的,这里设置为 CPU 核数的 1-4 倍最合理
    • 如果业务代码为同步 IO,需要根据请求响应时间和系统负载来调整,例如:100-500
    • 默认设置为 swoole_cpu_num(),最大不得超过 swoole_cpu_num() * 1000
    • 假设每个进程占用 40M 内存,100 个进程就需要占用 4G 内存

max_request

设置 **worker** 进程的最大任务数。【默认值:0 即不会退出进程】。

一个 worker 进程在处理完超过此数值的任务后将自动退出,进程退出后会释放所有内存和资源。

这个参数的主要作用是解决由于程序编码不规范导致的 PHP 进程内存泄露问题。PHP 应用程序有缓慢的内存泄漏,但无法定位到具体原因、无法解决,可以通过设置 max_request 临时解决,需要找到内存泄漏的代码并修复,而不是通过此方案。

设置此参数可能会产生的影响:

  • 客户端重连(BASE 模式)
  • 内存峰值大
  • 无法常驻内存
  • 首次请求慢(opcache, ext minits)
  • 提示
    • 达到 max_request 不一定马上关闭进程,参考 max_wait_time
    • SWOOLE_BASE 下,达到 max_request 重启进程会导致客户端连接断开

worker 进程内发生致命错误或者人工执行 exit 时,进程会自动退出。master 进程会重新启动一个新的worker 进程来继续处理请求。

max_conn (max_connection)

服务器程序,最大允许的连接数。【默认值:ulimit -n】。

max_connection => 10000, 此参数用来设置 Server 最大允许维持多少个 TCP 连接。超过此数量后,新进入的连接将被拒绝。

  • 提示
    • 默认设置
      • 应用层未设置 max_connection,底层将使用 ulimit -n 的值作为缺省设置
      • 4.2.9 或更高版本,当底层检测到 ulimit -n 超过 100000 时将默认设置为 100000,原因是某些系统设置了 ulimit -n100 万,需要分配大量内存,导致启动失败
    • 最大上限
      • 请勿设置 max_connection 超过 1M
    • 最小设置
      • 此选项设置过小底层会抛出错误,并设置为 ulimit -n 的值。
      • 最小值为 (worker_num + task_worker_num) * 2 + 32

serv->max_connection is too small.

- **<font style="color:rgb(44, 62, 80);">内存占用</font>**
    * <font style="color:rgb(233, 105, 0);background-color:rgb(248, 248, 248);">max_connection</font><font style="color:rgb(52, 73, 94);"> 参数不要调整的过大,根据机器内存的实际情况来设置。</font><font style="color:rgb(233, 105, 0);background-color:rgb(248, 248, 248);">Swoole</font><font style="color:rgb(52, 73, 94);"> 会根据此数值一次性分配一块大内存来保存 </font><font style="color:rgb(233, 105, 0);background-color:rgb(248, 248, 248);">Connection</font><font style="color:rgb(52, 73, 94);"> 信息,一个 </font><font style="color:rgb(233, 105, 0);background-color:rgb(248, 248, 248);">TCP</font><font style="color:rgb(52, 73, 94);"> 连接的 </font><font style="color:rgb(233, 105, 0);background-color:rgb(248, 248, 248);">Connection</font><font style="color:rgb(52, 73, 94);"> 信息,需要占用 </font><font style="color:rgb(233, 105, 0);background-color:rgb(248, 248, 248);">224</font><font style="color:rgb(52, 73, 94);"> 字节。</font>
  • 注意

max_connection 最大不得超过操作系统 ulimit -n 的值,否则会报一条警告信息,并重置为 ulimit -n 的值

WARN swServer_start_check: serv->max_conn is exceed the maximum value[100000]. WARNING set_max_connection: max_connection is exceed the maximum value, it’s reset to 10240

task_worker_num

配置** Task 进程的数量。**

配置此参数后将会启用 task 功能。所以 Server 务必要注册 onTaskonFinish 2 个事件回调函数。如果没有注册,服务器程序将无法启动。

  • 提示
    • 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 进程
  • 注意

Task 进程内不能使用 Swoole\Server->task 方法

task_max_request

设置** task 进程的最大任务数。**【默认值:0

设置 task 进程的最大任务数。一个 task 进程在处理完超过此数值的任务后将自动退出。这个参数是为了防止 PHP 进程内存溢出。如果不希望进程自动退出可以设置为 0。

heartbeat_check_interval

启用心跳检测【默认值:false

此选项表示每隔多久轮循一次,单位为秒。如 heartbeat_check_interval => 60,表示每 60 秒,遍历所有连接,如果该连接在 120 秒内(heartbeat_idle_time 未设置时默认为 interval 的两倍),没有向服务器发送任何数据,此连接将被强制关闭。若未配置,则不会启用心跳,该配置默认关闭,参考 Swoole 官方视频教程

  • 提示
    • Server 并不会主动向客户端发送心跳包,而是被动等待客户端发送心跳。服务器端的 heartbeat_check 仅仅是检测连接上一次发送数据的时间,如果超过限制,将切断连接。
    • 被心跳检测切断的连接依然会触发 onClose 事件回调
  • 注意 heartbeat_check 仅支持 TCP 连接

heartbeat_idle_time

连接最大允许空闲的时间

需要与 heartbeat_check_interval 配合使用

1
2
3
4
5
6
array(
// 表示一个连接如果600秒内未向服务器发送任何数据,此连接将被强制关闭
'heartbeat_idle_time' => 600,
// 表示每60秒遍历一次
'heartbeat_check_interval' => 60,
);
  • 提示
    • 启用 heartbeat_idle_time 后,服务器并不会主动向客户端发送数据包
    • 如果只设置了 heartbeat_idle_time 未设置 heartbeat_check_interval 底层将不会创建心跳检测线程,PHP 代码中可以调用 heartbeat 方法手动处理超时的连接

reload_async

设置异步重启开关。【默认值:true

设置异步重启开关。设置为 true 时,将启用异步安全重启特性,Worker 进程会等待异步事件完成后再退出。详细信息请参见 如何正确的重启服务

reload_async 开启的主要目的是为了保证服务重载时,协程或异步任务能正常结束。

1
$server->set(['reload_async' => true]);
  • 协程模式
    • 4.x 版本中开启 enable_coroutine 时,底层会额外增加一个协程数量的检测,当前无任何协程时进程才会退出,开启时即使 reload_async => false 也会强制打开 reload_async

max_wait_time

设置** **Worker** **进程收到停止服务通知后最大等待时间【默认值:3

经常会碰到由于 worker 阻塞卡顿导致 worker 无法正常 reload, 无法满足一些生产场景,例如发布代码热更新需要 reload 进程。所以,Swoole 加入了进程重启超时时间的选项。详细信息请参见 如何正确的重启服务

  • 提示
    • 管理进程收到重启、关闭信号后或者达到** **max_request** **时,管理进程会重起该** **worker** **进程。分以下几个步骤:
      • 底层会增加一个 (max_wait_time) 秒的定时器,触发定时器后,检查进程是否依然存在,如果是,会强制杀掉,重新拉一个进程。
      • 需要在 onWorkerStop 回调里面做收尾工作,需要在 max_wait_time 秒内做完收尾。
      • 依次向目标进程发送 SIGTERM 信号,杀掉进程。
  • 注意

v4.4.x 以前默认为 30

enable_coroutine

是否启用异步风格服务器的协程支持

enable_coroutine 关闭时在事件回调函数中不再自动创建协程,如果不需要用协程关闭这个会提高一些性能。参考什么是 Swoole 协程

  • 配置方法
    • php.ini 配置 swoole.enable_coroutine = ‘Off’ (可见 ini 配置文档 )
    • $server->set([‘enable_coroutine’ => false]); 优先级高于 ini
  • enable_coroutine** **选项影响范围
    • onWorkerStart
    • onConnect
    • onOpen
    • onReceive
    • setHandler
    • onPacket
    • onRequest
    • onMessage
    • onPipeMessage
    • onFinish
    • onClose
    • tick/after 定时器

开启 enable_coroutine 后在上述回调函数会自动创建协程

  • enable_coroutine 设置为 true 时,底层自动在 onRequest 回调中创建协程,开发者无需自行使用 go 函数创建协程
  • enable_coroutine 设置为 false 时,底层不会自动创建协程,开发者如果要使用协程,必须使用 go 自行创建协程,如果不需要使用协程特性,则处理方式与 Swoole1.x 是 100% 一致的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$server = new Swoole\Http\Server("127.0.0.1", 9501);

$server->set([
//关闭内置协程
'enable_coroutine' => false,
]);

$server->on("request", function ($request, $response) {
if ($request->server['request_uri'] == '/coro') {
go(function () use ($response) {
co::sleep(0.2);
$response->header("Content-Type", "text/plain");
$response->end("Hello World\n");
});
} else {
$response->header("Content-Type", "text/plain");
$response->end("Hello World\n");
}
});

$server->start();

task_enable_coroutine

开启** **Task** **协程支持。【默认值:false】,v4.2.12 起支持

开启后自动在 onTask 回调中创建协程和协程容器PHP 代码可以直接使用协程 API

  • 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$server->on('Task', function ($serv, Swoole\Server\Task $task) {
//来自哪个 Worker 进程
$task->worker_id;
//任务的编号
$task->id;
//任务的类型,taskwait, task, taskCo, taskWaitMulti 可能使用不同的 flags
$task->flags;
//任务的数据
$task->data;
//投递时间,v4.6.0版本增加
$task->dispatch_time;
//协程 API
co::sleep(0.2);
//完成任务,结束并返回数据
$task->finish([123, 'hello']);
});
  • 注意

task_enable_coroutine 必须在 enable_coroutinetrue 时才可以使用
开启 task_enable_coroutineTask 工作进程支持协程
未开启 task_enable_coroutine,仅支持同步阻塞

max_coroutine/max_coro_num

设置当前工作进程最大协程数量。【默认值:100000,Swoole 版本小于 v4.4.0-beta 时默认值为 3000

超过 max_coroutine 底层将无法创建新的协程,服务端的 Swoole 会抛出 exceed max number of coroutine 错误,TCP Server 会直接关闭连接,Http Server 会返回 Http 的 503 状态码。

Server 程序中实际最大可创建协程数量等于 worker_num * max_coroutine,task 进程和 UserProcess 进程的协程数量单独计算。

1
2
3
$server->set(array(
'max_coroutine' => 3000,
));