workerman 5.2.3 原生支持 sse 流式推送,只需正确设置响应头、保持连接、按格式分块输出;关键点包括设置 content-type、禁用缓存、使用 timer 非阻塞推送、nginx 关闭缓冲及客户端用 eventsource 自动重连。

Workerman 5.2.3 原生支持 SSE 流式推送,不需要额外扩展或协议层封装。它本质是 HTTP 长连接的持续响应,而 Workerman 的 Http 协议组件完全能胜任——只要正确设置响应头、保持连接不关闭、按 SSE 格式分块输出数据即可。
下面直接说关键点和可运行的写法:
正确设置 SSE 响应头与连接状态
SSE 要求服务端:
- 返回
Content-Type: text/event-stream - 禁用缓存:
Cache-Control: no-cache、Connection: keep-alive - 使用 UTF-8 编码(PHP 默认是
default_charset,建议显式设) - 不能提前结束响应体(即不能 return 或 exit)
$http_worker->onMessage = function ($connection, $request) {
// 判断是否为 SSE 请求(比如路径 /sse)
if ($request->path() === '/sse') {
// 设置 SSE 必需响应头
$connection->header('Content-Type', 'text/event-stream; charset=utf-8');
$connection->header('Cache-Control', 'no-cache');
$connection->header('Connection', 'keep-alive');
$connection->header('X-Accel-Buffering', 'no'); // 关键!防止 Nginx 缓冲
// 发送初始注释(可选,用于心跳或调试)
$connection->send(": connected\n\n");
// 模拟持续推送(真实场景中可监听 Redis、队列、协程任务等)
$i = 0;
while ($connection->connected) {
$data = json_encode(['time' => date('H:i:s'), 'count' => ++$i], JSON_UNESCAPED_UNICODE);
$connection->send("data: {$data}\n\n");
// 每秒推一次(注意:不要用 sleep() 在高并发下阻塞进程)
// 更推荐使用定时器 + 异步方式(见后文)
\Workerman\Lib\Timer::add(1, function () use ($connection, $data) {
if ($connection->connected) {
$connection->send("data: {$data}\n\n");
}
}, [], false);
break; // 退出循环,靠定时器维持推送
}
return;
}
// 其他普通请求(如 HTML 页面)
if ($request->path() === '/') {
$html = '<div id="log"></div><script>
const es = new EventSource("/sse");
es.onmessage = e => { document.getElementById("log").innerHTML += e.data + "<br>"; };
es.onerror = e => console.error("SSE error", e);
</script>';
$connection->header('Content-Type', 'text/html; charset=utf-8');
$connection->send($html);
}
};
注意连接生命周期与资源管理
- Workerman 中每个
$connection是一个独立对象,$connection->connected属性可实时判断是否仍在线; -
禁止在
onMessage回调里用sleep()—— 它会阻塞整个进程,破坏异步模型; - 推荐用
\Workerman\Lib\Timer::add()启动非阻塞定时任务,或结合Redis::pconnect()+SUBSCRIBE实现事件驱动推送; - 若需广播给多个客户端,把
$connection存入全局数组(如$_connections[$id] = $connection),推送时遍历检查connected状态再发。
Nginx 反向代理配置(生产环境必加)
如果前端经过 Nginx,必须关闭其缓冲行为,否则 SSE 数据会被攒够一定量或超时才吐出:
location /sse {
proxy_pass http://workerman_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_off;
proxy_buffering off;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
proxy_max_temp_file_size 0;
# 关键:禁用缓存 & 强制流式透传
proxy_cache_bypass 1;
proxy_no_cache 1;
}
客户端只需标准 EventSource
<script>
const es = new EventSource('/sse');
es.onmessage = e => console.log('收到:', JSON.parse(e.data));
es.addEventListener('error', () => console.warn('连接异常'));
</script>
EventSource 自带重连机制(默认 3 秒),断线后自动恢复,无需手动处理。
不复杂但容易忽略。











