discard_timeout_request 在连接接入初期即判断“注定超时”并丢弃,避免资源占用和请求积压;它基于已耗时+保底开销与request_timeout比较,在reactor阶段决策,不进入worker或业务逻辑。

开启 discard_timeout_request 后,Swoole 不会在请求真正超时后才丢,而是在确认它「注定超时」时提前丢——这和传统 timeout 机制有本质区别。
为什么不能等 request 真正 timeout 再丢?
等到 request_time_out 触发时,请求往往已排队、已分发、甚至已开始执行(比如在 worker 中解析 HTTP 头、反序列化 body)。此时丢弃,资源(CPU、内存、连接上下文)已被占用,后面的请求反而被拖慢。尤其在高并发 pipeline 场景下,一个注定超时的请求卡在中间模块,会导致后续所有请求延迟累积。
典型表现:
- 监控看到大量
timeout错误,但goodput(SLO 内完成请求数)不升反降 - worker 进程 CPU 使用率高,但实际有效吞吐低
- 用
swoole_server->stats()查看,connection_count高而request_count增长缓慢
discard_timeout_request 实际怎么判断「注定超时」?
它不是靠预测,而是基于当前连接的已耗时 + 最小可预期处理开销(如协议解析、路由分发)+ 配置的 request_timeout 做静态估算。只要当前已过时间 + 保底开销 > request_timeout,就立即丢弃,不进入业务逻辑。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
关键点:
- 只在连接刚接入、尚未交给 worker 前判断(即主进程或 reactor 线程阶段)
- 不依赖业务代码里的
sleep、curl、数据库等待等动态耗时 - 对 HTTP/HTTPS 请求有效;TCP 长连接需配合
heartbeat_check_interval和heartbeat_idle_time才能触发 - 启用前提:必须设置
request_timeout,否则该选项无意义
和 task_worker 的 discard 策略容易混淆的地方
这个配置和线程池的 DiscardPolicy 或 DiscardOldestPolicy 完全无关——它不作用于 task 投递队列,也不影响 swoole_server->task() 的行为。它是纯网络层、连接生命周期早期的丢弃,发生在任何 task 分发之前。
常见误配:
- 开了
discard_timeout_request却没设request_timeout→ 实际不生效 - 以为它能丢掉正在执行的 PHP 业务逻辑 → 不能,它只管「还没进业务」的连接
- 在
onReceive里手动 sleep 10 秒,指望它被丢 → 不会,此时早已过了 discard 判断点
真正需要它发挥作用的场景,是突发流量打进来、连接堆积、但业务处理路径又相对固定(比如 API 网关、静态路由服务)。这时候早一毫秒丢,后面就多一毫秒留给可能成功的请求。










