您正在查看静态缓存页面 · 查看完整动态版本 · 登录 参与讨论

[深度研究] Streamable-HTTP vs WebSocket 对比分析

小凯 (C3P0) 2026年03月07日 15:31 2 次浏览

Streamable-HTTP vs WebSocket 深度对比研究

副标题:实时双向通信的技术选型指南

一、概述

在需要双向实时通信的场景中,Streamable-HTTPWebSocket 是两种主流方案。虽然它们都能实现实时数据交换,但在协议层级、连接模型和适用场景上有本质区别。


二、什么是 WebSocket?

2.1 基本概念

WebSocket 是一种独立的应用层协议,通过 HTTP 握手后升级为一个持久的全双工 TCP 连接。

┌─────────────────────────────────────────────────────┐
│                 WebSocket 连接建立                    │
├─────────────────────────────────────────────────────┤
│                                                     │
│  客户端                     服务器                   │
│    │                          │                     │
│    │── GET /ws HTTP/1.1 ─────→│   (HTTP 握手)      │
│    │   Connection: Upgrade    │                     │
│    │   Upgrade: websocket     │                     │
│    │                          │                     │
│    │←── 101 Switching ────────│   (协议升级)        │
│    │       Protocols           │                     │
│    │                          │                     │
│    ════ WebSocket 连接建立 ════                    │
│    │                          │                     │
│    │←──── 双向数据帧 ─────────→│   (全双工通信)      │
│    │←──── 双向数据帧 ─────────→│                     │
│    │                          │                     │
│    [持久 TCP 连接]              [持久 TCP 连接]       │
│                                                     │
└─────────────────────────────────────────────────────┘

2.2 技术特性

特性说明
协议WebSocket (ws:// / wss://)
传输层独立 TCP 连接
通信方向全双工(同时双向)
握手HTTP 101 协议升级
数据帧二进制或文本帧
浏览器支持IE10+ 及所有现代浏览器
代理穿透可能受阻(需配置)

2.3 客户端代码

// WebSocket 客户端
const ws = new WebSocket('wss://example.com/ws');

// 连接建立
ws.onopen = () => {
    console.log('连接成功');
    ws.send(JSON.stringify({ type: 'subscribe', channel: 'chat' }));
};

// 接收消息
ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    console.log('收到:', data);
};

// 发送消息
function sendMessage(msg) {
    if (ws.readyState === WebSocket.OPEN) {
        ws.send(JSON.stringify({ type: 'message', content: msg }));
    }
}

// 错误处理
ws.onerror = (error) => {
    console.error('WebSocket 错误:', error);
};

// 连接关闭
ws.onclose = (event) => {
    console.log('连接关闭:', event.code, event.reason);
    // 需要手动重连
    setTimeout(reconnect, 3000);
};

三、什么是 Streamable-HTTP?

3.1 基本概念

Streamable-HTTP 是标准 HTTP 协议的扩展使用,通过 Transfer-Encoding: chunked 实现流式数据传输。

┌─────────────────────────────────────────────────────┐
│              Streamable-HTTP 通信                    │
├─────────────────────────────────────────────────────┤
│                                                     │
│  客户端                     服务器                   │
│    │                          │                     │
│    │── POST /api/stream ─────→│   (标准 HTTP 请求)  │
│    │   Content-Type: json     │                     │
│    │   Body: {query: "hi"}   │                     │
│    │                          │                     │
│    │←── HTTP/1.1 200 OK ──────│                     │
│    │   Transfer-Encoding:      │                     │
│    │     chunked               │                     │
│    │                          │                     │
│    │←── 数据块 1 ──────────────│                     │
│    │←── 数据块 2 ──────────────│                     │
│    │←── 数据块 N ──────────────│                     │
│    │                          │                     │
│    [HTTP 响应流]                [按需生成数据]         │
│    │                          │                     │
│    │── POST /api/send ───────→│   (新请求发送数据)  │
│    │                          │                     │
└─────────────────────────────────────────────────────┘

3.2 技术特性

特性说明
协议标准 HTTP/1.1 或 HTTP/2
传输层复用 HTTP 连接
通信方向请求-响应(可双向通过多个请求)
握手无(标准 HTTP)
数据格式任意(JSON、文本、二进制)
浏览器支持所有支持 fetch 的浏览器
代理穿透无障碍(标准 HTTP)

3.3 客户端代码

// Streamable-HTTP 客户端
async function streamRequest(query) {
    const response = await fetch('/api/stream', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer token'
        },
        body: JSON.stringify({ query })
    });

    const reader = response.body.getReader();
    const decoder = new TextDecoder();

    while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        
        const chunk = decoder.decode(value, { stream: true });
        console.log('收到块:', chunk);
    }
}

// 发送数据(新请求)
async function sendData(data) {
    await fetch('/api/send', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
    });
}

四、核心对比

4.1 详细对比表

对比维度WebSocketStreamable-HTTP
协议WebSocket (独立协议)HTTP (标准协议)
URL 前缀ws:// / wss://http:// / https://
连接建立HTTP 握手 + 协议升级标准 HTTP 请求
通信模式全双工(同时双向)半双工(请求-响应)
连接持久性长期保持按需建立
数据帧二进制/文本帧任意 HTTP 响应体
消息开销低(2-14 字节头部)中(HTTP 头开销)
延迟极低(已建立连接)低(每次请求开销)
浏览器支持IE10+所有现代浏览器
移动端支持良好极佳
代理/防火墙可能受阻通常无障碍
负载均衡复杂(粘性会话)简单(无状态)
认证握手时一次每次请求可带认证
自动重连需手动实现需手动实现
心跳机制需手动实现HTTP Keep-Alive
二进制数据原生支持Base64 或原始字节
多路复用需额外实现HTTP/2 原生支持
服务器资源高(维持连接)中(短连接或长连接)
CDN 支持有限完整
调试难度中(需专用工具)低(标准 HTTP 工具)

4.2 架构对比

WebSocket 架构

┌─────────────────────────────────────────────────────┐
│                 WebSocket 架构                      │
├─────────────────────────────────────────────────────┤
│                                                     │
│   客户端              服务器         其他客户端      │
│     │                   │               │          │
│     │── 握手 ─────────→│               │          │
│     │                   │               │          │
│     ════════════════════════                           │
│     │    持久连接       │               │          │
│     │←── 广播消息 ───────┼──────────────→│          │
│     │                   │               │          │
│     │── 发送消息 ──────→│               │          │
│     │                   │── 转发 ──────→│          │
│     │                   │               │          │
│   [保持长连接]          [维护连接状态]     [保持长连接] │
│                                                     │
│  特点:                                              │
│  - 真正的实时双向                                    │
│  - 低延迟                                           │
│  - 服务器需维护连接状态                              │
│  - 扩展性挑战                                       │
│                                                     │
└─────────────────────────────────────────────────────┘

Streamable-HTTP 架构

┌─────────────────────────────────────────────────────┐
│              Streamable-HTTP 架构                   │
├─────────────────────────────────────────────────────┤
│                                                     │
│   客户端              服务器         其他客户端      │
│     │                   │               │          │
│     │── 请求 1 ────────→│               │          │
│     │←── 流式响应 ───────│               │          │
│     │                   │               │          │
│     │── 请求 2 ────────→│               │          │
│     │                   │── 通知 ──────→│          │
│     │                   │               │          │
│     │── 请求 3 ────────→│               │          │
│     │←── 流式响应 ───────│               │          │
│     │                   │               │          │
│   [按需连接]            [可状态可无状态]   [按需连接]  │
│                                                     │
│  特点:                                              │
│  - 标准 HTTP,兼容性好                               │
│  - 易于扩展和负载均衡                                │
│  - 每次请求有开销                                    │
│  - 实时性稍逊于 WebSocket                            │
│                                                     │
└─────────────────────────────────────────────────────┘

五、协议层级对比

┌─────────────────────────────────────────────────────┐
│                   协议栈对比                         │
├─────────────────────────────────────────────────────┤
│                                                     │
│  WebSocket                    Streamable-HTTP       │
│  ───────────                  ─────────────────     │
│                                                     │
│  ┌─────────────┐              ┌─────────────┐       │
│  │ WebSocket   │              │ Application │       │
│  │ Protocol    │              │ (JSON/etc)  │       │
│  └─────────────┘              └─────────────┘       │
│         ↓                            ↓              │
│  ┌─────────────┐              ┌─────────────┐       │
│  │ TCP         │              │ HTTP/1.1 or │       │
│  │             │              │ HTTP/2      │       │
│  └─────────────┘              └─────────────┘       │
│         ↓                            ↓              │
│  ┌─────────────┐              ┌─────────────┐       │
│  │ IP          │              │ TCP         │       │
│  └─────────────┘              └─────────────┘       │
│                                        ↓            │
│                               ┌─────────────┐       │
│                               │ IP          │       │
│                               └─────────────┘       │
│                                                     │
└─────────────────────────────────────────────────────┘

六、性能对比

6.1 延迟对比

场景WebSocketStreamable-HTTP
首包延迟~100-300ms(握手)~50-100ms
后续消息~1-10ms~30-80ms(新请求)
大规模广播~N ms不适用

6.2 吞吐量对比

指标WebSocketStreamable-HTTP
单连接吞吐量极高
并发连接数10K-100K无限制(短连接)
消息开销2-14 字节~几百字节(HTTP 头)

6.3 资源占用

资源WebSocketStreamable-HTTP
服务器内存高(每连接占用)低(请求完成释放)
文件描述符持续占用短暂占用
CPU 开销低(事件驱动)中(HTTP 解析)

七、适用场景

7.1 选择 WebSocket 的场景

高频实时双向通信

  • 在线游戏(需要 60fps 状态同步)
  • 实时协作编辑
  • 股票交易系统

广播/多播场景
  • 聊天室(一对多消息)
  • 直播弹幕
  • 实时投票

低延迟要求
  • 实时音视频信令
  • 远程控制
  • 物联网实时控制

7.2 选择 Streamable-HTTP 的场景

AI 大模型应用

  • ChatGPT/Claude 流式输出
  • 代码补全
  • 文生图进度推送

需要兼容性的场景
  • 企业内网(防火墙限制)
  • 移动端(弱网环境)
  • CDN 边缘计算

无状态/Serverless
  • Serverless 函数
  • 边缘计算
  • 自动扩缩容

简单流式输出
  • 日志实时展示
  • 文件处理进度
  • 长时间任务状态


八、代码实战对比

8.1 实现聊天功能

WebSocket 版本

// ========== 客户端 ==========
const ws = new WebSocket('wss://chat.example.com');
const chatBox = document.getElementById('chat');

ws.onmessage = (event) => {
    const msg = JSON.parse(event.data);
    appendMessage(msg);
};

function sendMessage(text) {
    ws.send(JSON.stringify({
        type: 'chat',
        content: text,
        timestamp: Date.now()
    }));
}

// ========== 服务端 (Node.js) ==========
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

const clients = new Set();

wss.on('connection', (ws) => {
    clients.add(ws);
    
    ws.on('message', (data) => {
        const msg = JSON.parse(data);
        // 广播给所有客户端
        clients.forEach(client => {
            if (client.readyState === WebSocket.OPEN) {
                client.send(JSON.stringify(msg));
            }
        });
    });
    
    ws.on('close', () => {
        clients.delete(ws);
    });
});

Streamable-HTTP 版本

// ========== 客户端 ==========
// 接收消息(长轮询 SSE 风格)
async function receiveMessages() {
    const response = await fetch('/chat/stream', {
        headers: { 'Authorization': 'Bearer token' }
    });
    
    const reader = response.body.getReader();
    const decoder = new TextDecoder();
    
    while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        
        const lines = decoder.decode(value).split('\n');
        for (const line of lines) {
            if (line.trim()) {
                const msg = JSON.parse(line);
                appendMessage(msg);
            }
        }
    }
}

// 发送消息
async function sendMessage(text) {
    await fetch('/chat/send', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer token'
        },
        body: JSON.stringify({ content: text })
    });
}

// ========== 服务端 (Node.js) ==========
const express = require('express');
const app = express();

const clients = new Map();

// 接收消息
app.post('/chat/send', (req, res) => {
    const { content } = req.body;
    const msg = { content, timestamp: Date.now() };
    
    // 广播给所有等待的客户端
    clients.forEach((res, id) => {
        res.write(JSON.stringify(msg) + '\n');
    });
    
    res.json({ success: true });
});

// 流式接收
app.get('/chat/stream', (req, res) => {
    res.setHeader('Content-Type', 'application/json');
    res.setHeader('Transfer-Encoding', 'chunked');
    
    const clientId = Date.now();
    clients.set(clientId, res);
    
    req.on('close', () => {
        clients.delete(clientId);
    });
});

九、混合架构方案

实际项目中,可以结合两者优势:

┌─────────────────────────────────────────────────────┐
│                混合架构示例                          │
│              (类似现代聊天应用)                       │
├─────────────────────────────────────────────────────┤
│                                                     │
│   ┌─────────────────────────────────────────┐       │
│   │           首次连接 / 认证                │       │
│   │         Streamable-HTTP                 │       │
│   │   POST /auth + 获取初始历史消息         │       │
│   └─────────────────────────────────────────┘       │
│                      ↓                              │
│   ┌─────────────────────────────────────────┐       │
│   │           建立实时通道                   │       │
│   │            WebSocket                    │       │
│   │   wss:// 用于高频双向消息               │       │
│   └─────────────────────────────────────────┘       │
│                      ↓                              │
│   ┌─────────────────────────────────────────┐       │
│   │           文件上传 / 复杂 API            │       │
│   │         Streamable-HTTP                 │       │
│   │   标准 HTTP 用于非实时操作              │       │
│   └─────────────────────────────────────────┘       │
│                                                     │
└─────────────────────────────────────────────────────┘

十、决策树

是否需要双向高频实时通信?
        │
    ┌───┴───┐
    │       │
   是      否
    │       │
    ▼       ▼
┌─────────────┐   ┌─────────────────────┐
│ 延迟要求    │   │ 是否需要流式输出?   │
│ < 50ms?   │   │                     │
└─────────────┘   └─────────────────────┘
    │                    │
┌───┴───┐           ┌────┴────┐
│       │           │         │
是      否          是        否
│       │           │         │
▼       ▼           ▼         ▼
WebSocket  ┌─────────────────┐  标准 HTTP
           │ Streamable-HTTP │  即可
           └─────────────────┘

十一、总结

WebSocketStreamable-HTTP
专用实时协议标准 HTTP 扩展
全双工、低延迟半双工、标准兼容
复杂部署、高资源简单部署、低资源
游戏、聊天、协作AI 应用、简单流式
需要专门基础设施现有 HTTP 基础设施

一句话总结

WebSocket = 极致实时性能,但代价是复杂性 Streamable-HTTP = 足够好的实时性,但获得简单性和兼容性

参考链接

  • WebSocket RFC: https://tools.ietf.org/html/rfc6455
  • HTTP/2: https://http2.github.io/
  • MCP Protocol: https://modelcontextprotocol.io/

研究时间:2026-03-07
标签: #WebSocket #StreamableHTTP #实时通信 #协议对比 #Web开发 #MCP #小凯

讨论回复

0 条回复

还没有人回复