buffer_output_size 是单次 send 的硬性字节数上限,非总缓冲池大小;设太小导致截断,设太大易引发 oom,且与 socket_buffer_size 协同影响大数据传输稳定性。

buffer_output_size 控制单次 send 的最大字节数
这个配置不是“总缓冲池大小”,而是每次调用 Server->send()、WebSocket\Server->push() 或 Http\Response->end() 时,允许写入底层输出缓冲区的上限。超过该值会直接报错:Fatal error: Uncaught Swoole\Exception: invalid buffer_output_size(设为 0 或负数时),或在运行时触发 ERR_EMPTY_RESPONSE、响应截断(比如 JSON 大对象只返回前半段)。
常见误判是把它当成“连接级总缓存”——其实它只管“这一笔 send 能塞多少”。哪怕你设成 128MB,也只影响这一次调用;下一次 send 还得重新过这个阈值。
- 设太小(如默认 2MB):模板渲染大 HTML、返回 10MB PDF、推送视频帧 chunk 都可能失败
- 设太大(如 >64MB):单次 send 占满 worker 内存,尤其高并发时易触发 OOM,且不解决根本瓶颈
- 注意:用
$response->sendfile()时,该配置完全不生效——走的是内核sendfile零拷贝路径,绕过用户态缓冲
和 socket_buffer_size 的关键区别在哪
buffer_output_size 是 per-request / per-send 的硬限制;socket_buffer_size 是 per-connection 的总发送缓冲上限(即 TCP socket 发送队列能堆积多少待发数据)。两者作用层级不同,但会叠加影响大数据传输行为。
举个典型卡顿场景:B 用户带宽只有 1Mbps,你却持续以 5MB/s 向他 push 数据。即使每次 send 都 ≤ buffer_output_size,数据仍会在内核 socket 发送缓冲区堆积。等堆积量突破 socket_buffer_size(默认 2MB),就会触发错误:swFactoryProcess_finish:send failed,session#1 output buffer has been overflowed,连接被静默断开。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
-
buffer_output_size影响“能不能发出去这一笔” -
socket_buffer_size影响“发出去的这些笔,能不能先存着慢慢送” - 二者都偏小 → 响应截断 + 连接频繁断开
- 只调大
buffer_output_size但忽略socket_buffer_size→ 仍会因堆积溢出而丢连接
大数据传输时真正该优先考虑的路径选择
盲目调大 buffer_output_size 并不能提升吞吐,反而掩盖设计缺陷。真实高负载场景(如直播、文件分发)应主动避开用户态缓冲:
- 静态文件优先用
$response->sendfile('/path/to/file'):走sendfile系统调用,零拷贝,不占 PHP 内存,不受buffer_output_size限制 - 动态大内容拆成小 chunk 推送:配合客户端心跳或流式接收逻辑,每次 send 控制在 128KB–1MB,避免单次压爆
- 对极慢终端(如弱网移动端),服务端需实现背压(backpressure):检测
Server->isEstablished($fd)和发送返回值,暂停推送直到客户端消费完上一批 - 别依赖增大缓冲硬扛——网络延迟和带宽差异是客观存在的,缓冲只是临时容器,不是扩容硬盘
容易被忽略的协程与内存实际开销
很多人以为调大 buffer_output_size 只影响“这次请求”,其实它会按 worker 数预估内存:启动时每个 worker 都会预留一块大小为 buffer_output_size 的输出缓冲池。设成 32MB × 16 个 worker,光这部分就吃掉 512MB 内存,还没算 socket_buffer_size 和协程栈。
更隐蔽的问题是:当使用 Swoole\Coroutine\Http\Client 调用另一个 Swoole 服务时,若对方开启了 http_compression,但 buffer_output_size 不够容纳压缩后完整响应头+体,就会出现 $client->headers 为空、状态码错乱——因为压缩后的边界帧被截断了,解析器直接失效。
缓冲参数从来不是孤立存在的,它嵌在 TCP 栈、内核 socket 缓冲、协程调度、甚至 HTTP 压缩链路里。调一个值之前,先确认数据到底走哪条通路。










