• Swoole从入门到入土(3)——TCP服务器[基本配置项]


    在这一节的开篇,让我们先解决上一节的“配置”话题。对于server对象,有很多配置项决定了服务端的行为,可以用set的函数进行配置的设置。

    1、函数set:用于设置运行时的各项参数。服务器启动后通过 $serv->setting 来访问 Server->set 方法设置的参数数组。

    SwooleServer->set(array $setting): void

    $setting:配置项数组。

    注意:函数set必须在 Server->start() 前调用。

    示例:

    $server->set(array(
        'reactor_num'   => 2,     // reactor thread num
        'worker_num'    => 4,     // worker process num
        'backlog'       => 128,   // listen backlog
        'max_request'   => 50,
        'dispatch_mode' => 1,
    ));

    每个配置项的意义,下面会进行介绍。

    2、常用配置项

    1) 属性reactor_num:设置启动的 Reactor 线程数。【默认值:CPU 核数】什么是reactor线程呢?点击这里查看上一节常识科普

    说明:

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

    建议设置为 CPU 核数的 1-4 倍,但最大不得超过 swoole_cpu_num() * 4。

    2) worker_num:设置启动的 Worker 进程数。【默认值:CPU 核数】什么是Worker进程呢?点击这里查看上一节常识科普

    说明:

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

    举例:

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

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

    说明:

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

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

    达到 max_request 不一定马上关闭进程,参考 max_wait_time。

    SWOOLE_BASE 下,达到 max_request 重启进程会导致客户端连接断开。

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

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

    说明:

    经常会碰到由于 worker 阻塞卡顿导致 worker 无法正常 reload, 无法满足一些生产场景,例如发布代码热更新需要 reload 进程。所以,我们加入了进程重启超时时间的选项。

    管理进程收到重启、关闭信号后或者达到 max_request 时,管理进程会重起该 worker 进程。分以下几个步骤:

        · 底层会增加一个 (max_wait_time) 秒的定时器,触发定时器后,检查进程是否依然存在,如果是,会强制杀掉,重新拉一个进程。

        · 需要在 onWorkerStop 回调里面做收尾工作,需要在 max_wait_time 秒内做完收尾。

        · 依次向目标进程发送 SIGTERM 信号,杀掉进程。

    5) backlog:设置 Listen 队列长度

    举例:

    如 backlog => 128,此参数将决定最多同时有多少个等待 accept 的连接。

    说明:

    关于 TCP 的 backlog

        · 我们知道 TCP 有三次握手的过程,客户端 syn=>服务端 syn+ack=>客户端 ack,当服务器收到客户端的 ack 后会将连接放到一个叫做 accept queue 的队列里面(linux2.2 之后握手过程分为 syn queue 和 accept queue 两个队列,syn queue 长度由 tcp_max_syn_backlog 决定)

        · 队列的大小由 backlog 参数和配置 somaxconn 的最小值决定,我们可以通过 ss -lt 命令查看最终的 accept queue 队列大小,Swoole 的主进程调用 accept(高版本内核调用的是 accept4,为了节省一次 set no block 系统调用)

        · 从 accept queue 里面取走。 当 accept queue 满了之后连接有可能成功(成功是通过 TCP 的重传机制,相关的配置有 tcp_synack_retries 和 tcp_abort_on_overflow)

        · 也有可能失败,失败后客户端的表现就是连接被重置( 客户端收到 syn+ack 包就认为连接成功了,实际上服务端还处于半连接状态,有可能发送 rst 包给客户端,客户端的表现就是 Connection reset by peer

        · 或者连接超时,而服务端会记录失败的记录,可以通过 netstat -s|grep 'times the listen queue of a socket overflowed 来查看日志。如果出现了上述现象,你就应该调大该值了。 幸运的是 Swoole 的 SWOOLE_PROCESS 模式与 PHP-FPM/Apache 等软件不同,并不依赖 backlog 来解决连接排队的问题。所以基本不会遇到上述现象。

    6) dispatch_mode:数据包分发策略。【默认值:2】

    说明:

    建议:

    无状态 Server 可以使用 1 或 3,同步阻塞 Server 使用 3,异步非阻塞 Server 使用 1

    有状态使用 2、4、5

    在UDP模式下:

    dispatch_mode=2/4/5 时为固定分配,底层使用客户端 IP 取模散列到不同的 Worker 进程,算法为 ip2long(ClientIP) % worker_num

    dispatch_mode=1/3 时随机分配到不同的 Worker 进程

    dispatch_mode 配置在 SWOOLE_BASE 模式是无效的,因为 BASE 不存在投递任务,当收到客户端发来的数据后会立即在当前线程 / 进程回调 onReceive,不需要投递 Worker 进程。

    注意:

    dispatch_mode=1/3 时,底层会屏蔽 onConnect/onClose 事件,原因是这 2 种模式下无法保证 onConnect/onClose/onReceive 的顺序;

    非请求响应式的服务器程序,请不要使用模式 1 或 3。例如:http 服务就是响应式的,可以使用 1 或 3,有 TCP 长连接状态的就不能使用 1 或 3。

    Swoole最基本配置项就以上这些啦,这一篇到这里就结束了,其它的配置项,包括重启、心跳机制会在之后的文章中慢慢介绍。大家下期见

    ---------------------------  我是可爱的分割线  ----------------------------

    最后博主借地宣传一下,漳州编程小组招新了,这是一个面向漳州青少年信息学/软件设计的学习小组,有意向的同学点击链接,联系我吧。

  • 相关阅读:
    LINQ to XML 示例(转)
    (jQuery,Highcharts)前端图表系列之一 Highcharts (转)
    c#中Split等分割字符串的几种方法(转)
    Highcharts 强大的jQuery图表制作功能
    OpenFileDialog、SaveFileDialog常用屬性、對話框用法及得到系統特殊文件夾路徑(转)
    C# Regex 深入正则表达式(转)
    C#文件IO操作(转)
    免费Google地图API使用说明(转)
    Java遍历集合的几种方法分析(实现原理、算法性能、适用场合)
    C++ Web 开发框架 (CppCMS)
  • 原文地址:https://www.cnblogs.com/ddcoder/p/13604775.html
Copyright © 2020-2023  润新知