Skip to content

关于 Reactor 请求分配的问题 #5797

@suyar

Description

@suyar

本文将讨论以下问题:高并发下,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 => enabled

Directive => 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 以上:

Image
Image

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一直居高不下,占用率第二的是定时任务:
Image
Image

看起来似乎其他处理请求的 worker 都在划水,emmm....
不死心的我看了下其他业务的容器,发现都是相同情况。

上述相关 issue 中,@matyhtf 有提到:dispatch_mode=2/4/5 这些固定分配的模式,如果并发客户端数量比 Worker 进程少,一定是无法利用所有Worker进程的。,但是我的并发肯定是超过 8 个 worker 的数量的,还是会出现这种场景。考虑到以后大概率会引入 websocket,所以目前并不适合去改 dispatch_mode=1/3.

假设是这样的话,是不是表示 Reactor 线程在分配请求到 worker 的时候,根据 fd 并不能很好的做到均衡?
当前我的做法是额外启动了两个容器,用 nginx 做了负载均衡,暂时解决了容器 cpu100% 的问题,P90 延迟也恢复了正常。

问题&猜想

Image

  1. dispatch_mode=2 的模式下,Reactor 线程是根据什么来分发请求到 worker 的?
  2. 在文档中看到了 dispatch_mode=7 的模式,但是文档中并没有过多描述使用场景,什么情况下可以使用?
  3. swoole 配置中,为了防止意外的内存泄漏,配置了 max_request 参数,这个参数会导致 worker 重建,是否会影响 fd 的分配平衡?
  4. 有什么调整建议,才能让请求相对均匀的分配到各个 worker?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions