package_max_length是内存安全阀,防止未完成数据包过度占用内存;开启协议解析后,swoole需缓存未收全的数据,若不设该值,畸形大包将导致内存暴涨、连接静默关闭或http 400错误。

它不是“上传文件大小限制”的开关,而是内存安全阀——决定单个数据包最多能占多少内存。
为什么必须设 package_max_length?
开启 open_length_check、open_eof_check 或 open_http_protocol 后,Swoole 会把未收完的数据暂存在内存里,等拼成完整包再交给业务逻辑。如果客户端发一个 100MB 的畸形包(比如伪造的 Content-Length),而你没设 package_max_length,那这 100MB 就真会一直卡在内存里,直到超时或崩溃。
常见错误现象:
– 内存占用随连接数线性暴涨,top 看到 PHP 进程 RSS 持续飙升
– open_eof_check 开启后,大文件上传失败但无明确报错,只看到连接被静默关闭
– HTTP POST 超过默认 8KB 时直接返回 400,连 onRequest 都没触发
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- HTTP 协议下:
GET请求硬限制 8KB,不可调;POST依赖Content-Length头,超package_max_length直接 400 + 关连接 - EOF 协议下:数据持续追加到缓存,直到遇到
package_eof或超过package_max_length才丢弃 - Length 协议下:靠包头解析长度,一旦解析出的长度 >
package_max_length,立刻丢弃并关连接(不进内存)
怎么设才合理?
不能拍脑袋填个 2G —— 它是单连接单包上限,不是全局总和。假设你有 5000 个长连接,每个都卡住一个 2M 的未完成包,那就是 10GB 内存白占。
- HTTP 场景:上传文件最大 50MB → 设
package_max_length => 52428800(50 * 1024 * 1024) - WebSocket / 自定义 TCP:按业务协议最大帧长设,比如 LLM 流式响应单帧不超过 1MB → 填
1048576 - 纯文本 EOF 协议(如 \r\n 分隔):通常 64KB~1MB 足够,填
1048576是较安全起点 - 别设成 0 或省略:Swoole 会用默认值(通常是 2MB 或 8MB),但不同版本/协议行为不一致,显式声明更可控
容易踩的坑
package_max_length 不是万能的,它只管“单包”,不管“多包”或“连接总量”。
- 设了
package_max_length但忘了开open_length_check:长度检测不生效,照样吃内存 - 用
open_eof_check却设太小(比如 1KB):正常换行日志(含 \r\n)也可能被截断,导致合包失败 - Hyperf/Laravel-Swoole 等框架中,该配置必须写在
server.set层,写在中间件或请求处理器里无效 - 和
upload_tmp_dir混淆:前者控内存,后者控磁盘临时文件路径,两者要协同 —— 内存上限设高了,磁盘空间也得跟上
真正难的是权衡:设太小,业务包被误杀;设太大,内存风险上升。建议上线前用异常流量压测 —— 比如故意发超长 Content-Length 或连续不带 EOF 的大数据块,看是否按预期丢弃并释放内存。










