PHP如何将已生成页面发送给客户端,无需等待后续阻塞IO操作完成
具体实现方案
你需要的send_output_to_client()核心逻辑是主动刷出所有输出缓冲,同时告知客户端响应内容已全部传输完成,无需继续等待连接断开,代码实现如下:
function send_output_to_client() { // 若开启了会话,先关闭会话锁,避免后续阻塞操作导致同用户其他请求被挂起 if (session_id()) { session_write_close(); } // 告知Nginx等反向代理不要缓存当前响应,直接透传给客户端 header('X-Accel-Buffering: no'); // 告知客户端响应内容总长度,收到对应字节后即可结束本次请求 header('Content-Length: ' . ob_get_length()); // 告知客户端无需保持长连接 header('Connection: close'); // 刷出所有层级的PHP输出缓冲 while (ob_get_level() > 0) { ob_end_flush(); } // 强制将服务端缓冲区的内容推送到客户端 flush(); }
注意事项
- 后续的
perform_blocking_IO_operation()绝对不能再产生任何输出,否则会和已发送的Content-Length头不匹配,导致客户端响应异常 - 若开启了gzip等响应压缩功能,需要先关闭当前请求的压缩,否则计算出的内容长度是压缩前的大小,和实际传输的压缩后大小不符
- 如果使用Apache mod_php运行,需要确认Apache的输出缓冲模块未强制拦截缓冲内容,否则提前推送逻辑可能失效
- 如果你的阻塞IO操作是可异步的非核心逻辑,也可以考虑将其丢入后台队列消费,完全避免对前端请求的影响,改造成本略高但稳定性更强
内容的提问来源于stack exchange,提问作者Basj
相关产品推荐
相关产品推荐

