maxpackagesize设置不生效是因为未正确赋值给tcpconnection类静态属性,必须在worker::runall()前全局设置tcpconnection::$maxpackagesize,且仅在协议类input()返回包长时才校验。

maxPackageSize 设置不生效?检查是否写错作用域
Workerman 的 maxPackageSize 是静态属性,必须直接赋值给 TcpConnection 类,而不是实例或 Worker 实例。常见错误是把它写在 $worker->onMessage 回调里,或者误当成 Worker 配置项传入 new Worker() 构造函数 —— 这些写法完全无效。
正确写法只有一种:
TcpConnection::$maxPackageSize = 2 * 1024 * 1024; // 2MB
必须放在 Worker::runAll() 之前,且全局仅需设置一次。如果用了多个 Worker(如 HTTP + WebSocket),这个值对所有基于 TcpConnection 的协议都生效。
为什么设了 maxPackageSize 还收到超大包?协议层没走 input 方法
这个参数只在 Workerman 调用协议类的 input() 方法后才起作用 —— 它会把 input() 返回的包长和 maxPackageSize 比较。如果你用的是原始 TCP 连接、没定义协议类,或者协议类的 input() 返回 false(表示数据不完整、继续等待),那这个校验根本不会触发。
所以实际防御效果取决于你是否正确实现了协议解析逻辑:
- WebSocket 协议:内置
input(),自动受控 - HTTP 协议:内置
input(),但只校验单次请求头+体总长(不含分块传输) - 自定义二进制协议:必须自己在
input()中解析出包长度并返回,否则不校验 - 纯
onMessage回调无协议类:maxPackageSize完全不生效
设太小导致正常业务失败?注意 multipart/form-data 的实际长度
上传文件时,multipart/form-data 请求体包含边界符、字段名、文件头等大量冗余数据,实际字节数远大于原始文件大小。例如一个 5MB 的图片,封装后可能达 5.2MB 甚至更高。若将 maxPackageSize 设为 5MB,该请求就会被直接断连。
建议按以下方式估算并留出余量:
- 文件上传场景:设为预期最大文件体积 × 1.2,再向上取整到 MB 级(如支持 50MB 文件,设
60 * 1024 * 1024) - 纯 JSON 消息:通常 1–2MB 足够,设 2MB 可覆盖绝大多数异常大 payload
- 不要低于 1MB:过小会误杀合法长消息(如日志批量上报、配置同步)
同时记得,PHP 层的 upload_max_filesize 和 post_max_size 对 Workerman 无效,但前端或反向代理(如 Nginx)仍可能拦截,需一并检查。
maxPackageSize 不是万能防火墙,它不防内存耗尽和 CPU 打满
这个参数只做连接级长度拦截:包长超标 → 主动 close 连接。但它不阻止攻击者快速建立大量连接并发送接近阈值的“合法大包”,从而耗尽内存或打满 CPU。
真正防住大包攻击,需要组合策略:
- 配合连接数限制:用
$worker->count控制进程数,再结合系统级ulimit -n防爆开文件描述符 - 前置反向代理限流:Nginx 设置
client_max_body_size和limit_req,在流量入口就压住 - 应用层校验:在
onMessage中检查业务逻辑允许的最大数据量(比如用户头像不能超 5MB),超限直接 send error 并 close - 监控异常连接:记录频繁触发
maxPackageSize断连的 IP,加入临时黑名单
单独依赖 maxPackageSize 就像只关一扇窗却忘了锁门 —— 它有用,但只是防线中的一环,且容易被绕过。真正关键的是理解它在哪生效、在哪失效,以及它背后没有解决的问题是什么。











