send_yield 并不存在于 swoole 任何稳定版本中;send 是同步非阻塞调用,返回 true/null/false 表示不同发送状态,不挂起协程,背压需手动控制。

send_yield 不是 Swoole 的公开 API,它并不存在于任何稳定版本的 Swoole(包括 5.x 和 6.x)中。你很可能混淆了几个概念:协程挂起行为、send 的返回值语义、以及某些旧版文档或社区误传的命名。
send 在发送缓冲区满时的真实表现
send 是同步非阻塞调用,它的行为与底层 socket 发送缓冲区状态强相关:
- 返回
true:数据已成功写入操作系统 socket 发送缓冲区(注意:不是发到对端) - 返回
null:数据暂存于 Swoole 应用层缓冲区,等待下一次 reactor 轮询时再尝试刷入 socket 缓冲区 - 返回
false:发送失败,常见原因包括客户端断连、fd 无效、或应用层缓冲区也满了(默认上限 2MB)
缓冲区满 ≠ 程序卡死。Swoole 内部会把未发出的数据暂存在连接对象的应用层缓冲区,并在下一轮事件循环中重试。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
你无法靠“加 yield”来“等它发完”——因为 send 本身不挂起协程,它只是个立即返回的函数。
为什么有人以为有 send_yield?
这个说法通常来自两类误解:
- 把
sendwait当成send_yield:sendwait是阻塞式发送(底层调用write()直到写完或出错),会真正让当前协程等待,但它不感知缓冲区水位,也不做流量控制,容易拖垮整个协程调度器,生产环境应避免使用 - 把协程 sleep + 重试当成“yield 版 send”:有人手动写循环,
while ($server->send($fd, $data) === null) { Co::sleep(0.001); },这其实是在模拟背压等待,但效率低、精度差、且掩盖了根本问题
正确应对发送缓冲区压力的方式
- 主动降速:监听
onBufferFull回调,在连接缓冲区快满时暂停投递新数据(比如暂停推送、降低心跳频率) - 启用自动限流:
buffer_high_watermark和buffer_low_watermark配合onBufferFull/onBufferEmpty实现闭环控制 - 拆大包为小包:单次
send数据不要超过 64KB,避免触发内核分片或应用层缓冲区膨胀 - 检查客户端消费能力:如果对方接收慢(如弱网设备、未及时
recv),再快的send也无意义;此时应考虑业务层 ACK 或滑动窗口机制
send 从不自动 yield,也不会因缓冲区满而挂起协程——它只返回 null 表示“这次没发出去,我记下了,下次再试”。真正的背压控制必须由你显式设计,而不是依赖一个不存在的 send_yield。










