如何在Cloudflare Workers中实现SSE?现有方案返回响应后即终止
在Cloudflare Workers中正确实现Server-Sent Events(SSE)
我懂你碰到的问题——Cloudflare Workers的运行模型和普通服务器不一样,你的代码之所以返回响应后立刻终止,是因为两个关键错误:
- 错误设置了响应状态码
101:这是用于协议切换(比如WebSocket)的,SSE本质是普通的HTTP长连接,应该用200状态码。 - 没有把定时任务和Worker的生命周期绑定:Cloudflare Workers在返回响应后,如果没有活跃的异步任务或流操作,会立即终止进程,你的
setInterval根本没机会持续运行。
修正后的完整实现
下面是可以稳定运行的SSE代码,我会一步步解释关键点:
export default { async fetch(request) { // 处理OPTIONS预检请求(如果需要跨域) if (request.method === 'OPTIONS') { return new Response(null, { headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET,OPTIONS', 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept', }, }); } // 创建AbortController监听客户端断开连接,及时清理资源 const controller = new AbortController(); const { signal } = controller; // 创建可读流,用于推送SSE事件 const stream = new ReadableStream({ start(controller) { // 定时器每隔5秒推送一次消息 const intervalId = setInterval(() => { try { // SSE格式必须严格:data: 内容\n\n const message = `data: Hello from Cloudflare Workers at ${new Date().toISOString()}\n\n`; controller.enqueue(new TextEncoder().encode(message)); } catch (err) { // 如果客户端断开,会抛出错误,清理定时器 clearInterval(intervalId); controller.error(err); } }, 5000); // 客户端断开连接时触发,清理定时器 signal.addEventListener('abort', () => { clearInterval(intervalId); controller.close(); }); }, // 当客户端暂停接收时触发,可以暂停推送 pull(controller) { // 这里可以根据需要处理暂停逻辑,比如缓存消息 }, cancel() { // 流被取消时清理资源 console.log('SSE connection closed by client'); }, }); // 设置正确的响应头 const headers = new Headers({ 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache, no-transform', 'Connection': 'keep-alive', 'Access-Control-Allow-Origin': '*', // 告诉Cloudflare不要缓存响应,保持长连接 'CF-Cache-Status': 'DYNAMIC', }); // 返回200状态码的响应,绑定AbortController的signal return new Response(stream, { status: 200, headers, signal, }); }, };
关键细节说明
- 状态码与响应头:必须用
200状态码,同时设置CF-Cache-Status: DYNAMIC避免Cloudflare缓存或中断长连接。 - AbortController:用来监听客户端断开事件,及时清理定时器,避免Worker资源泄漏。
- ReadableStream的生命周期:通过
controller.enqueue推送消息,流会保持连接直到客户端断开或主动关闭,这样Worker进程会一直保持活跃直到连接结束。 - 跨域处理:添加了OPTIONS预检请求的处理,根据你的实际需求调整
Access-Control-Allow-Origin的值。
为什么你的原始代码不行?
status: 101是错误的,SSE不需要切换协议,用普通HTTP响应即可。- 你创建的
TransformStream没有和Worker的生命周期绑定,返回响应后Worker进程被立即终止,setInterval根本无法持续执行。
Cloudflare Workers的限制注意
- 免费计划的Worker长连接最长维持时间为10分钟,付费计划可以延长。
- 不要在SSE连接中执行密集计算,避免触发Worker的资源限制。
内容的提问来源于stack exchange,提问作者Tector




