-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Description
本文将讨论以下问题:高并发下,dispatch_mode=2
时 Reactor 在分配请求到 Worker 时负载不均衡
查找到的相关 issue
事件背景
之前业务稳定日活在2万左右,容器的 cpu 一直稳定在 50% 以下,最近两天堆量日活达到6万,容器 cpu100% 预警,并且 P90 出现了从 50ms 飙升到了 2000ms,遂进行了如下排查:
- 容器是否进行了资源限制:否
- 是否内存泄漏:否(容器内存占用200M)
- 服务器资源:CPU8核(使用率60%),32G内存(使用率55%),磁盘IO(iops和io读写均未达到上限的50%),服务器负载(5-16之间波动)
- 使用框架:hyperf(SWOOLE_PROCESS模式)
- 是否有出现 mysql、redis 连接池等待超时:无;容器日志、框架日志均未出现现象级错误
- PHP版本:8.2.15
- 请求链路:nginx -> hyperf(run in docker)
PHP扩展安装列表
[PHP Modules] apcu bcmath bz2 calendar Core ctype curl date dom exif FFI fileinfo filter ftp gd gettext hash iconv igbinary imagick intl json libxml mbstring mysqli mysqlnd openssl pcntl pcre PDO pdo_mysql Phar posix random readline redis Reflection session shmop SimpleXML sockets sodium SPL standard swoole sysvmsg sysvsem sysvshm tokenizer xml xmlreader xmlwriter xsl yaml Zend OPcache zip zlib[Zend Modules]
Zend OPcache
Swoole扩展信息
Swoole => enabled Author => Swoole Team Version => 5.1.1 Built => Dec 1 2023 13:40:51 coroutine => enabled with boost asm context epoll => enabled eventfd => enabled signalfd => enabled cpu_affinity => enabled spinlock => enabled rwlock => enabled sockets => enabled openssl => OpenSSL 1.1.1f 31 Mar 2020 dtls => enabled http2 => enabled json => enabled curl-native => enabled pcre => enabled mutex_timedlock => enabled pthread_barrier => enabled futex => enabled mysqlnd => enabled async_redis => enabledDirective => Local Value => Master Value
swoole.enable_coroutine => On => On
swoole.enable_library => On => On
swoole.enable_fiber_mock => Off => Off
swoole.enable_preemptive_scheduler => Off => Off
swoole.display_errors => On => On
swoole.use_shortname => Off => Off
swoole.unixsock_buffer_size => 8388608 => 8388608
TCP连接数活跃在 5K 以上:
Swoole setting 相关配置如下:
array:10 [
"enable_coroutine" => true
"worker_num" => 8
"pid_file" => "/www/runtime/hyperf.pid"
"open_tcp_nodelay" => true
"max_coroutine" => 100000
"open_http2_protocol" => true
"max_request" => 10000
"socket_buffer_size" => 2097152
"buffer_output_size" => 104857600
"package_max_length" => 104857600
]
其中 dispatch_mode
未配置,默认值未 2
.
对容器内进程进行排查,发现几乎只有一个 worker 进程的CPU一直居高不下,占用率第二的是定时任务:
看起来似乎其他处理请求的 worker 都在划水,emmm....
不死心的我看了下其他业务的容器,发现都是相同情况。
上述相关 issue 中,@matyhtf 有提到:dispatch_mode=2/4/5 这些固定分配的模式,如果并发客户端数量比 Worker 进程少,一定是无法利用所有Worker进程的。
,但是我的并发肯定是超过 8 个 worker 的数量的,还是会出现这种场景。考虑到以后大概率会引入 websocket,所以目前并不适合去改 dispatch_mode=1/3
.
假设是这样的话,是不是表示 Reactor 线程在分配请求到 worker 的时候,根据 fd
并不能很好的做到均衡?
当前我的做法是额外启动了两个容器,用 nginx 做了负载均衡,暂时解决了容器 cpu100% 的问题,P90 延迟也恢复了正常。
问题&猜想
dispatch_mode=2
的模式下,Reactor 线程是根据什么来分发请求到 worker 的?- 在文档中看到了
dispatch_mode=7
的模式,但是文档中并没有过多描述使用场景,什么情况下可以使用? - swoole 配置中,为了防止意外的内存泄漏,配置了
max_request
参数,这个参数会导致 worker 重建,是否会影响 fd 的分配平衡? - 有什么调整建议,才能让请求相对均匀的分配到各个 worker?