swoole学习之: 服务端(异步风格)-TCP/UDP服务器 - 配置

本文详细介绍了Swoole服务端异步风格的TCP/UDP服务器配置,包括reactor_num、worker_num、max_request等参数,帮助理解如何优化服务器性能和管理进程。此外,还涵盖了task相关设置、内存管理和并发控制等关键配置项。
摘要由CSDN通过智能技术生成

服务端(异步风格) - TCP/UDP服务器 - 配置

> 本文摘自官方文档 https://wiki.swoole.com/#/server/setting , 手打

Server->set() 函数用于设置 Server 运行时的各项参数. > 从4.5.5版本开始, 底层会检查设置的配置项, 如果不是Swoole提供的配置项抛出Warning: "PHP Warning: unsupported option [xxx] in xxxx".

reactor_num

设置启动的 reactor 线程数 , 默认值: CPU核数( swoole_cpu_num )。

用来设置主进程内事件处理线程的数量, 每个线程都会维持一个 EventLoop . 线程之间是无锁的, 指令可以被所有cpu核心并行执行. 可设置线程数为 CPU核数( swoole_cpu_num )的1-4倍。

worker_num

设置启动的Worker进程数 , 默认值: CPU核数( swoole_cpu_num )。

  • 如果业务代码是全异步IO的, 建议设置为CPU核数( swoole_cpu_num )的1-4倍
  • 如果业务代码为同步IP, 需要根据请求响应时间和系统负载来调整, 例如: 100-500
  • 默认设置为CPU核数( swoole_cpu_num ), 但最大不得超过CPU核数的100倍

如果1个请求耗时100ms, 则一个进程处理速度是10Req/s, 要提供1000 QPS的处理能力, 至少要设置100个进程.

如何查看进程的内存占用? 这里我们只看 RSS(Resideng Set Size, 实际使用物理内存, 包含共享库占用的内存).

  • top 命令的第六列RES
  • ps -aux 的第六列RSS
  • cat /proc/进程id/status | grep RSS , 比如: 我们通过 ps -aux | grep redis 得到redis的进程id是2164, 然后我们查看redis的内存占用: cat /proc/2164/status | grep RSS

官方教程

max_request

设置 worker 进程的最大任务数 。 默认值为0, 表示不会退出进程。

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

该参数的主要作用是解决由于程序编码不规范导致的PHP内存泄漏问题. 如果PHP应用程序有缓慢的内存泄漏, 但是无法确定到具体的原因,无法解决, 则可以通过设置 max_request 临时 解决. 可以通过 Swoole_Tracker 发现泄漏的代码.

注意:

  • 达到 max_request 不一定马上关闭进程, 这与 max_wait_time (进程收到停止服务通知后最大等待时间, 默认3s)有关.
  • 在SWOOLE_BASE模式下, 达到max_request重启进程会导致客户端连接断开. > 当worker进程内发生致命错误或者人工执行exit时进程自动退出. master进程会重新启动一个新的worker进程来继续处理请求.

max_conn (max_connection)

服务器的最大允许的连接数 . 默认值 ulimit -n , 取值范围: [ (worker_num + task_worker_num) * 2 + 32 , 100万].

  • 内存占用: 一个TCP连接的 Connection 信息占用 224 Bytes

task_worker_num

配置 Task 进程的数量 . 最大值: CPU核数( swoole_cpu_num )的1000倍

因为task功能不会自动启动, 必须通过设置该参数才会启动, 且 必须 注册 onTask , onFinish 这两个回调函数.

Task进程是同步阻塞的, 所以需要根据单个task的处理耗时和投递的速度来设置进程数.

task_worker_num = 任务投递的速度 / 每秒可处理的任务数

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

task_ipc_mode

设置 Task 进程与 Worker 进程之间通信的方式 . 默认值: 1, 表示使用 Unix_socket 通信.

模式:

  • 1: 使用 Unix_socket 通信(默认)
  • 2: 使用 sysvmsg 消息队列通信
  • 3: 使用 sysvmsg 消息队列通信, 并设置为争抢模式

提示:

  • 模式1:
    • 使用模式1时, 支持定向投递, 可在task和taskwait方法中使用 dst_worker_id 指定目标Task进程.
    • dst_workder_id 使用默认值-1时, 底层会判断每个Task进程的状态, 向当前空闲的进程投递任务.
  • 默认2,3
    • 消息队列模式使用os提供的内存队列存储数据, 未指定 message_queue_key 消息队列 key , 将使用私有队列, 在 Server 程序终止后会删除消息队列.
    • 指定消息队列 key Server 程序终止后, 消息队列中的数据不会删除, 因此进程重启后仍然能取到数据.
    • 可使用 ipcrm -q 消息队列ID 手动删除消息队列数据
    • 模式2 模式3 的不同之处是: 模式2 支持定向投递, $server->task($data, $task_worker_id) 可以指定要投递的task进程id. 模式3 是完全争抢模式, task进程会争抢队列, 无法使用定向投递, task/taskwait 将无法指定目标进程id, 即使指定了也无效.

task_max_request

设置task进程的最大任务数 , 默认值: 0.

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

task_tmpdir

设置task的数据临时目录 . 默认值: Linux /tmp 目录(内存文件系统).

Server 中, 如果投递的数据超过 8180 Bytes, 将启用临时文件来保存数据, 这些数据就保存在 task_tmpdir 设置的目录.

如果设置的 task_tmpdir 目录不存在, 底层会自动创建, 如果创建失败, Server->start 失败!

task_enable_coroutine

开启 Task 协程支持. 默认值: false , 自v4.2.12起支持.

  • 必须在 Server->set() 中设置 enable_coroutine=true :
$server->set([
   'enable_coroutine' => true,
   ....
]);

  • 开启后自动在 onTask 回调中创建协程和协程容器, PHP代码可以直接使用协程API;
  • 未开启时仅支持同步阻塞.

不完整示例:

  • 普通模式
$server->on('task', function(Swoole\Server $server, $task_id, $reactor_id, $data){
    // do something
});

  • 使用面向对象风格的 Task 回调格式(设置task_use_object=true)
$server->on('task', function(Swoole\Server $server, Swoole\Server\Task $task){
    echo 'Worker进程id: ' . $task->worker_id . PHP_EOL;
    echo '任务编号: ' . $task->id . PHP_EOL;
    echo '任务类型: ' . $task->flags . PHP_EOL;//taskwait,task, taskCo, taskWaitMulti 可能使用不同的flags
    echo '任务的数据: ' . $task->data . PHP_EOL;
    echo '投递时间: ' . $task->dispatch_time . PHP_EOL;
    //协程API
    co::sleep(0.2);
    //完成任务, 结束并返回
    $task->finish([123, 'hello']);
});

task_use_object / task_object

是否 使用面向对象风格的Task回调格式 , 别名 task_object 是v4.6.0新增的. 默认: false .

设置为 true 时, onTask 回调将变成对象模式.

示例:

$server = new Swoole\Server('127.0.0.1', 9501);
$server->set([
    'worker_num' => 1,
    'task_worker_num' => 3, //启动task
    'task_use_object' => true,//别名 task_object, 从v4.6起支持
]);
$server->on('receive', function(Swoole\Server $server, $fd, $task_id, $data){
    echo 'task_id=' . $task_id . ' 收到来自fd=' . $fd . '的数据: ' . trim($data) . PHP_EOL;
    //投递任务
    $server->task(['fd'=>$fd]);
});
//task收到任务: onTask事件回调, 返回对象模式
$server->on('task', function(Swoole\Server $server, Swoole\Server\Task $task){
    //给客户端发送信息
   $server->send($task->data['fd'], json_encode($server->stats()));
   //task任务完成, 通知Worker进程, 执行onFinish事件回调
   $server->finish($task->data);
});
//task任务完成
$server->on('finish', function(Swoole\Server $server, $task_id, $data){
    echo 'task_id=' . $task_id . ' finished';
});
$server->start();

dispatch_mode

数据包分发策略 . 默认值: 2 (固定模式, 根据$fd分配Worker)

模式:

  • 1: 轮循模式: 收到会轮循, 依次分配给每一个 Worker 进程

  • 2: 固定模式: 根据 $fd 分配 Worker , 保证同一个连接发来的数据只会被同一个 Worker 处理.

  • 3: 抢占模式: 主进程会根据 Worker 的忙闲状态选择投递, 只会投递给处于闲置状态的 Worker .

  • 4: IP分配: 根据客户端IP进行取模(取余), 分配给一个固定的Worker进程. 可以保证同一个来源IP的数据总会被分配到同一个 Worker 进程. 算法为: ip2long(ip) % worker_num .

  • 5: UID分配: 需要用户代码中调用 Server->bind() 将一个连接绑定一个 uid , 然后底层根据uid的值分配到不同的 Worker 进程, 算法为: UID % worker_num , 如果UID是字符串, 则 crc32(string UID)

  • 7: stream模式: 空闲的 Worker 进程会 accept (接受)请求, 并accept(接受) Reactor 的新请求. 提示 :

  • 使用建议:

    • 无状态 Server 可以使用 1 3 , 同步阻塞 Server 使用 3 , 异步 Server 使用 1 .
    • 有状态 Server 使用 2 , 4 , 5
  • UDP 协议

    • dispatch_mode=2, 4, 5 时为 固定 分配,底层使用客户端ip 取模 散列到不同的Worker进程, 算法为: ip2long(ip) % worker_num .
    • dispatch_mode=1, 3 随机 分配到不同
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值