max_concurrency 是 swoole\http\server 对“当前正在处理的 http 请求”数量的硬性限制,超限立即返回 503 错误并关闭连接,不排队、不等待;它独立于 max_coroutine 和 max_connection,仅在 $server->set() 中显式配置且启动前生效,默认为 0(不限制,生产环境须设具体值)。

max_concurrency 是 HTTP 服务器的并发请求数硬限
max_concurrency 只对 Swoole\Http\Server 生效,它不是协程数限制,也不是连接数限制,而是“当前正在处理的 HTTP 请求”数量上限。一旦活跃请求(即已进入 onRequest 回调、尚未调用 $response->end())超过该值,Swoole 底层会立即返回 HTTP 503 Service Unavailable 并关闭连接——不排队、不等待、不缓冲。
- 它和
max_coroutine无关:即使协程池还有空闲,只要 HTTP 层活跃请求数超限,照样 503 - 它和
max_connection无关:连接可以建满 10000,但若max_concurrency=100,第 101 个到达的 HTTP 请求仍会被秒拒 - 该参数仅控制「已解析 HTTP 头、进入业务逻辑」的请求,TCP 握手、TLS 握手、HTTP 头未收全的连接不计入
怎么设置 max_concurrency 才有效
必须在 $server->set() 中显式传入,且只在 Http\Server 实例中起作用:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
$server = new Swoole\Http\Server('0.0.0.0', 9501);
$server->set([
'max_concurrency' => 200, // ✅ 有效
'worker_num' => 4,
]);
- 默认值为
0,表示不限制(慎用!生产环境务必设具体值) - 不能动态修改:只能在
start()前设置,运行中改无效 - 注意单位是「请求数」,不是「协程数」或「连接数」;一个长轮询请求可能占着不释放,就会卡住后续请求
为什么设了 max_concurrency 还看到 503?常见误判点
看到 503 不一定就是 max_concurrency 触发的,要先排除其他更常见的 503 来源:
-
max_coroutine耗尽:协程创建失败时,onRequest根本进不去,日志里通常有coroutine create failed或直接 crash - Worker 进程被
max_request强制退出中:此时新请求可能被主进程暂挂或转给其他 Worker,但若全部 Worker 都处于“待退出”状态,也会临时 503 - 网关层拦截:比如 Nginx 配置了
proxy_next_upstream error timeout http_503,上游 Swoole 返回任意 503 都会被它二次转发或记录 - 业务代码主动
$response->status(503):这种是逻辑层控制,和max_concurrency无关
和信号量(Semaphore)混用时要注意什么
很多人用 Swoole\Coroutine\Semaphore 做业务级并发控制,但它和 max_concurrency 是两层机制,容易叠加出意料之外的行为:
- 假设
max_concurrency=50,又在onRequest里用sem->acquire()控制最多 10 个任务同时执行:实际并发请求仍可达 50,只是其中最多 10 个能真正跑业务,其余 40 个在acquire处阻塞——它们仍算作「活跃请求」,占用max_concurrency配额 - 结果就是:表面看没超限,但大量请求卡在 acquire 等待,响应延迟飙升,监控上
active_request_count持续接近 50,而真实吞吐却很低 - 正确做法:把信号量控制放在更前置的位置(如 Gateway 层),或用
Channel实现带超时的请求排队,避免让阻塞态请求挤占max_concurrency名额










