Skip to content
🔗 分享本题
查看我的学习进度 →

SSE 适合服务端单向持续推送,WebSocket 适合低延迟全双工实时交互

🧠 记忆锚点:只需服务端持续推送选 SSE;双方频繁实时互动选 WebSocket。

💡 答案要点

两种协议核心对比:

维度SSE(Server-Sent Events)WebSocket
通信方向单向(服务端 → 客户端)双向(全双工)
协议HTTP/1.1WS(基于 TCP 升级)
连接开销低(复用 HTTP)中(需握手升级)
浏览器支持原生支持,自动重连原生支持,需手动重连
负载均衡友好(标准 HTTP)需要粘性会话(sticky session)
适用场景LLM Token 流式输出实时双向交互、语音对话

选型决策树:

需要客户端实时向服务端发送消息(非HTTP请求)?
├── 是 → WebSocket
│         场景:语音助手、用户打断Agent、实时协作
└── 否
    需要服务端持续推送数据流?
    ├── 是 → SSE
    │         场景:LLM Token 流式输出、进度推送
    └── 否 → 普通 HTTP 轮询即可

SSE 实现(LLM 流式输出最佳选择):

展开 Python 代码示例(30 行)
python
# FastAPI SSE 示例
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import openai

app = FastAPI()

@app.post("/chat/stream")
async def chat_stream(query: str):
    async def generate():
        client = openai.AsyncOpenAI()
        stream = await client.chat.completions.create(
            model="gpt-4o",
            messages=[{"role": "user", "content": query}],
            stream=True
        )
        async for chunk in stream:
            if chunk.choices[0].delta.content:
                # SSE 格式:data: xxx\n\n
                yield f"data: {chunk.choices[0].delta.content}\n\n"
        yield "data: [DONE]\n\n"

    return StreamingResponse(
        generate(),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "X-Accel-Buffering": "no"  # 禁用 Nginx 缓冲
        }
    )

WebSocket 实现(需要双向交互):

python
# FastAPI WebSocket 示例(支持用户打断 Agent)
from fastapi import WebSocket

@app.websocket("/agent/ws")
async def agent_websocket(websocket: WebSocket):
    await websocket.accept()
    agent_task = None

    while True:
        # 同时监听用户消息和 Agent 输出
        data = await websocket.receive_text()
        msg = json.loads(data)

        if msg["type"] == "user_message":
            # 取消当前 Agent 任务(用户打断)
            if agent_task and not agent_task.done():
                agent_task.cancel()

            # 启动新 Agent 任务
            agent_task = asyncio.create_task(
                run_agent_and_stream(msg["content"], websocket)
            )

        elif msg["type"] == "interrupt":
            # 用户主动打断
            if agent_task:
                agent_task.cancel()
            await websocket.send_json({"type": "interrupted"})

面试话术:

"选 SSE 还是 WebSocket 看交互模式。LLM Token 流式输出用 SSE 最合适——单向推送、HTTP 友好、负载均衡无压力,Claude、ChatGPT 都用 SSE。但 Agent 场景需要用户'打断'或实时发工具执行结果时,就要 WebSocket——全双工,支持服务端推 + 客户端随时插话。我的原则:能用 SSE 就用 SSE,只有真正需要双向实时通信才上 WebSocket,因为 WebSocket 的粘性会话会让运维复杂很多。"