Open
Description
背景
Swoole\Http\Server
支持设置 max_concurrency
可限制最大并发。
gs->concurrency
- 此特性使用了
gs->concurrency
共享内存结构实现,类型为sw_atomic_t
(uint32_t
) - 使用原子计数进行自增自减,无需加锁。可安全地在多个工作进程、线程并行执行
worker->concurrency
当前工作进程的并发,使用 worker->concurrency
共享内存结构实现实现。因为只有当前工作进程修改,不存在并行执行,所以可直接使用 worker->concurrency++
和 worker->concurrency--
进行自增自减的计数操作。
异步重启
当开启了异步重启逻辑后,可能会出现新、旧工作进程同时存在,这可能会导致 worker->concurrency
同时被两个进程所修改。
- 旧的工作进程收到关闭指令后,立即执行一次计数器修复逻辑,这时新的进程并未启动,执行修复逻辑是安全的
- 并标记
SwooleWG.shutdown=true
表示当前进程正在退出,后续旧进行将不再修改worker->concurrency
和gs->concurrency
- 管理进程也会抛弃旧进程,即便旧的进程发生异常退出,也不会再执行修复逻辑
SwooleWG
是本地内存,非共享,因此仅在当前进程内有效,新的工作进程SwooleWG.shutdown
一定为false
涉及到的函数:
swoole_http_server_onBeforeRequest
swoole_http_server_onAfterResponse
修复 gs->concurrency
但若发生crash
或fatal error
时可能会出现 gs->concurrency
未能正确处理,因此需要额外的逻辑修复此计数。修复代码由多条指令组成,无法原子化。
auto value = worker->concurrency;
if (value > 0 && sw_atomic_value_cmp_set(&worker->concurrency, value, 0) == value) {
sw_atomic_sub_fetch(&gs->concurrency, value);
if ((int) gs->concurrency < 0) {
gs->concurrency = 0;
}
}
因此上述代码必须只能在旧的工作进程结束、新的工作进程启动之间执行,因此仅可在管理进程
的onWorkerError
回调中执行。
Metadata
Metadata
Assignees
Labels
No labels