Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

concurrency 计数器的优化 #88

Open
matyhtf opened this issue Oct 15, 2024 · 0 comments
Open

concurrency 计数器的优化 #88

matyhtf opened this issue Oct 15, 2024 · 0 comments

Comments

@matyhtf
Copy link
Member

matyhtf commented Oct 15, 2024

背景

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->concurrencygs->concurrency
  • 管理进程也会抛弃旧进程,即便旧的进程发生异常退出,也不会再执行修复逻辑

SwooleWG 是本地内存,非共享,因此仅在当前进程内有效,新的工作进程SwooleWG.shutdown一定为false

涉及到的函数:

  • swoole_http_server_onBeforeRequest
  • swoole_http_server_onAfterResponse

修复 gs->concurrency

但若发生crashfatal 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回调中执行。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant