惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recorded Future
Recorded Future
C
Cyber Attacks, Cyber Crime and Cyber Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Scott Helme
Scott Helme
Cyberwarzone
Cyberwarzone
C
CERT Recently Published Vulnerability Notes
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Palo Alto Networks Blog
Google Online Security Blog
Google Online Security Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
WordPress大学
WordPress大学
博客园 - 聂微东
L
LINUX DO - 最新话题
月光博客
月光博客
小众软件
小众软件
T
Troy Hunt's Blog
A
Arctic Wolf
量子位
I
Intezer
大猫的无限游戏
大猫的无限游戏
T
Tailwind CSS Blog
S
Schneier on Security
Schneier on Security
Schneier on Security
NISL@THU
NISL@THU
T
Threat Research - Cisco Blogs
TaoSecurity Blog
TaoSecurity Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园_首页
有赞技术团队
有赞技术团队
N
News and Events Feed by Topic
美团技术团队
The Cloudflare Blog
P
Privacy International News Feed
S
Security Affairs
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
G
GRAHAM CLULEY
N
News | PayPal Newsroom
Apple Machine Learning Research
Apple Machine Learning Research
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LINUX DO - 热门话题
V
Vulnerabilities – Threatpost
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
CXSECURITY Database RSS Feed - CXSecurity.com
宝玉的分享
宝玉的分享
Application and Cybersecurity Blog
Application and Cybersecurity Blog
IT之家
IT之家
Hacker News: Ask HN
Hacker News: Ask HN
雷峰网
雷峰网

博客园 - 若-飞

企业AI Agent落地的核心逻辑与路径 基于langchain,Function Call的成功率怎么解决? LangChain Checkpoint(检查点)是什么?—— Agent 的"存档机制" RAG 设计:Embedding 如何切分 AI 客服系统设计:RAG 知识库设计 Go 百万连接服务器设计:从网卡到业务的全链路解析 深度解析 sync.Pool:从设计哲学到生产实践 Goroutine 泄漏:原因、检测与防范 Go Channel 关闭与超时机制完全指南 Go Map 无限增长问题解决方案 LangChain 聊天记录压缩:原理、机制与实战 揭开 sklearn 文本分类的核心原理:从词袋到逻辑回归 大模型“胡说八道”怎么办?一张图读懂检测、评估与修复全方案 企业级AI知识库权限隔离设计:让AI“懂规矩”比“懂知识”更重要 RAG系统设计全解析:从架构到多模态的核心知识图谱 RAG召回率提升全攻略:7大核心方法让检索更精准 RAG召回率提升秘籍:Metadata过滤的底层原理与实践 构建更好的RAG系统:深入理解混合搜索 一文搞懂 RAG 中 Retriever 和 Reranker 的区别 一文搞懂 RAG 的召回率(Recall)是什么? LangChain / LangGraph、MCP、Harness Engineer 与 Claude Code 的对应关系 Agent Harness 技术笔记:从 Trajectory 到 Function Calling Loop BLEU 是什么?——从原理到工程实践 一文讲清:Approve / Permit / Permit2 的本质区别 分库分表后跨分页查询的完整方案 ai如何处理私有数据 ai幻觉是啥,以及如何解决 别再让大模型“凭空瞎猜”了!带你认识AI最强外挂:ChromaDB 用 useQuery 管请求:TanStack React Query 入门小结 HD钱包--BIP44 TRON 四种 API 面怎么选:从节点协议到 JSON-RPC 再到 TronGrid 以太坊节点存储与共识机制全解析 BSC节点发现协议全解析:UDP发现、Bootnode引导与Gossip交易广播 以太坊节点发现背后的分布式哈希表(DHT)与 Kademlia 原理解析 Solidity中的bytes与string:深入理解这两种特殊的动态数组 智能合约自毁:当资产还在,合约死了 —— 深度解析 selfdestruct 导致的资产锁定风险 TDengine CLI (taos) 使用指南 —— Docker 本地开发实战 在 macOS 上用 DBeaver 连接 TDengine:踩坑总结与最终配置指南 Solidity Storage Slot 深度解析 Geth Snapshot Export/Import 深度解析: 不是备份工具,而是数据分析利器 基于BSC 公链的数据备份与 Snapshot 机制深度解析 Docker 共享内存完全指南:从原理到实践,避免常见的理解误区 Docker容器"僵尸状态"问题排查与自动重启方案 TDengine vs MySQL:时序数据处理的时代之选 Proxmox 启用 QEMU Guest Agent 实战指南 解决 Blockscout "batch too large" 错误的完整指南 一文讲清楚什么是基准测试(Benchmark) Rust中的宏(Macro):编译时的代码生成魔法 Docker优雅关闭的艺术:为什么stop_grace_period能防止数据丢失 为什么 Go 没有依赖注入和 Bean 机制?语言设计哲学对比
SSE协议深度解析:被低估的HTTP服务器推送标准
若-飞 · 2026-01-06 · via 博客园 - 若-飞

引言:重新认识SSE

在实时通信的世界里,WebSocket的光芒常常盖过了它的兄弟——SSE(Server-Sent Events)。但你可能不知道,这个看似简单的技术背后,是一套优雅、成熟且被所有现代浏览器原生支持的HTTP标准协议。今天,让我们深入挖掘SSE的真相。

一、SSE的官方身份:W3C标准协议

不是"hack",是标准

很多人误以为SSE是某种HTTP连接的"hack"用法。实际上,SSE是一个完整的W3C标准:

标准文档:W3C Server-Sent Events Specification
当前状态:W3C Recommendation(正式推荐标准)
发布时间:2015年2月3日
标准链接https://www.w3.org/TR/eventsource/

// 这不是某个库的API,而是浏览器原生实现
const eventSource = new EventSource('/api/stream');
// 遵循W3C EventSource接口规范

协议栈定位

应用层:SSE协议(基于HTTP)
传输层:HTTP/1.1或HTTP/2(Keep-Alive连接)
网络层:TCP/IP
物理层:以太网/WiFi/5G

二、SSE协议的三要素:简单却强大

1. 必备响应头:text/event-stream

HTTP/1.1 200 OK
Content-Type: text/event-stream      # 核心标识
Cache-Control: no-cache               # 禁止缓存
Connection: keep-alive                # 保持连接
Transfer-Encoding: chunked            # 分块传输(可选)

关键点text/event-stream是IANA注册的标准MIME类型(RFC 2046),不是随意字符串。

2. 数据格式规范:严格的文本协议

// 一个完整的SSE消息单元
data: 这是消息内容\n            // 数据行(可多行)
data: 继续上一消息的第二行\n
id: 42\n                         // 消息ID(用于重连)
event: message\n                 // 事件类型
retry: 10000\n                   // 重连间隔(毫秒)
\n                               // 空行表示消息结束

// 浏览器接收到的对象:
{
  data: "这是消息内容\n继续上一消息的第二行",
  lastEventId: "42",
  type: "message"
}

3. 连接管理:HTTP Keep-Alive的创造性应用

// Go语言实现SSE连接的核心逻辑
func serveSSE(w http.ResponseWriter, r *http.Request) {
    // 1. 设置标准响应头
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    
    // 2. 获取刷新器(强制立即发送)
    flusher, _ := w.(http.Flusher)
    
    // 3. 保持HTTP连接,持续发送消息
    for {
        select {
        case <-r.Context().Done():
            return // 客户端断开
        case msg := <-messageChannel:
            // 4. 遵循SSE格式发送
            fmt.Fprintf(w, "data: %s\n\n", msg)
            flusher.Flush() // 立即发送到网络
        }
    }
    // 连接在函数返回或客户端断开时结束
}

三、协议工作原理:一次握手,无限推送

建立连接流程

客户端->服务器: GET /stream HTTP/1.1
客户端->服务器: Accept: text/event-stream
服务器->客户端: HTTP/1.1 200 OK
服务器->客户端: Content-Type: text/event-stream
服务器->客户端: Connection: keep-alive
服务器->客户端: 
服务器->客户端: data: 欢迎连接\n\n
服务器->客户端: data: 实时数据...\n\n
服务器->客户端: data: 持续推送...\n\n
Note right of 客户端: 连接保持打开
Note left of 服务器: 可随时推送新消息

消息流示例

客户端请求:
GET /api/events HTTP/1.1
Host: example.com
Accept: text/event-stream

服务器响应流:
HTTP/1.1 200 OK
Content-Type: text/event-stream
Connection: keep-alive

: 心跳保持连接
data: 用户alice登录
event: user-login
id: 101

data: {"temperature": 23.5}
event: sensor-data
id: 102

data: 系统即将维护
event: system-alert
id: 103
retry: 30000

... 持续不断 ...

四、SSE协议的先进特性

1. 自动重连机制

// 浏览器内置的重连逻辑
const es = new EventSource('/stream');

es.onerror = function(event) {
    // 自动重连流程:
    // 1. 关闭当前连接
    // 2. 等待 retry 指定的时间(默认3秒)
    // 3. 重新发起请求
    // 4. 如果设置了 Last-Event-ID,会自动发送
};

// 服务器可控制重连间隔
// retry: 10000 表示10秒后重试

2. 事件ID追踪

// 服务器端:发送带ID的消息
func sendMessageWithID(w io.Writer, id int, data string) {
    fmt.Fprintf(w, "id: %d\n", id)
    fmt.Fprintf(w, "data: %s\n\n", data)
}

// 断线重连时,浏览器会自动发送
// Last-Event-ID: 最后收到的消息ID
// 服务器可以据此发送遗漏的消息

3. 多事件类型支持

// 服务器发送不同类型事件
data: 普通消息\n
event: notification\n
\n

data: 温度: 23.5°C\n
event: sensor-update\n
\n

data: 用户123已登录\n
event: user-activity\n
\n

// 客户端分别监听
eventSource.addEventListener('notification', handleNotification);
eventSource.addEventListener('sensor-update', handleSensorUpdate);
eventSource.addEventListener('user-activity', handleUserActivity);

五、SSE与HTTP/2的完美结合

HTTP/1.1下的限制

// 浏览器限制:每个域名最多6个并发HTTP/1.1连接
// 如果打开6个SSE连接,其他AJAX请求会被阻塞

HTTP/2的优势

# HTTP/2的多路复用特性
# 一个TCP连接上可并行多个SSE流

客户端 → 打开一个TCP连接
     → 流1: GET /sensors/temperature
     → 流2: GET /sensors/humidity  
     → 流3: GET /notifications
     → 流4: POST /api/data (AJAX请求)
     → 所有流共享同一连接,互不阻塞

自动降级兼容

// 浏览器自动处理协议版本
const es = new EventSource('https://api.example.com/stream');
// 浏览器根据服务器支持情况选择HTTP/1.1或HTTP/2

六、SSE协议的适用场景

理想应用场景

不适合的场景

// 需要双向通信时(使用WebSocket)
// 如:在线游戏、视频聊天、实时对战

// 需要二进制数据传输时
// 如:文件传输、音视频流

// 需要低延迟控制消息时
// SSE有HTTP头部开销,WebSocket更轻量

七、协议安全性考量

1. 同源策略

// 默认遵循同源策略
const es = new EventSource('/api/stream'); // 同源,正常

// 跨域需要CORS
const es2 = new EventSource('https://other-domain.com/stream');
// 服务器必须响应:Access-Control-Allow-Origin: *

2. 认证与授权

// 方案1:Cookie自动携带
const es = new EventSource('/private-stream');
// Cookie自动在请求头中发送

// 方案2:URL参数
const es = new EventSource('/stream?token=abc123');

// 方案3:自定义头部(需要CORS预检)
// EventSource不支持自定义头部,这是限制

3. 安全最佳实践

// 服务器端安全措施
func secureSSEHandler(w http.ResponseWriter, r *http.Request) {
    // 1. 验证身份
    token := r.URL.Query().Get("token")
    if !validateToken(token) {
        http.Error(w, "Unauthorized", 401)
        return
    }
    
    // 2. 限制连接数
    if connectionCount > maxConnections {
        http.Error(w, "Too many connections", 429)
        return
    }
    
    // 3. 设置安全头
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("X-Content-Type-Options", "nosniff")
    
    // 4. 连接超时控制
    ctx, cancel := context.WithTimeout(r.Context(), 1*time.Hour)
    defer cancel()
    
    // ... SSE逻辑
}

八、性能优化策略

1. 连接复用

// 多个事件类型通过一个连接发送
func multiplexedSSE(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/event-stream")
    flusher, _ := w.(http.Flusher)
    
    go sendHeartbeats(w, flusher)
    go sendNotifications(w, flusher)
    go sendSystemStats(w, flusher)
    
    // 保持主goroutine运行
    <-r.Context().Done()
}

func sendHeartbeats(w io.Writer, flusher http.Flusher) {
    ticker := time.NewTicker(30 * time.Second)
    for range ticker.C {
        fmt.Fprintf(w, ": heartbeat\n\n")
        flusher.Flush()
    }
}

2. 数据压缩

// 启用HTTP压缩(文本数据压缩率高)
func compressedSSE(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Content-Encoding", "gzip") // 启用压缩
    
    gz := gzip.NewWriter(w)
    defer gz.Close()
    
    fmt.Fprintf(gz, "data: 压缩的消息内容\n\n")
    gz.Flush() // 需要同时刷新gzip writer和HTTP flusher
}

3. 智能心跳

// 自适应心跳间隔
func adaptiveHeartbeat(w io.Writer, flusher http.Flusher, ctx context.Context) {
    lastActivity := time.Now()
    heartbeatInterval := 30 * time.Second
    
    for {
        select {
        case <-ctx.Done():
            return
        case <-time.After(heartbeatInterval):
            if time.Since(lastActivity) > 25*time.Second {
                fmt.Fprintf(w, ": heartbeat\n\n")
                flusher.Flush()
            }
            // 动态调整心跳间隔
            if time.Since(lastActivity) < 5*time.Second {
                heartbeatInterval = 60 * time.Second // 活跃时减少心跳
            } else {
                heartbeatInterval = 30 * time.Second // 空闲时增加心跳
            }
        }
    }
}

九、协议对比:SSE vs WebSocket vs Long Polling

十、未来展望:SSE的演进

1. 与Web Push API结合

// 浏览器关闭时也能接收推送
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe();

// 服务器通过Push服务发送,即使页面关闭

2. QUIC/HTTP3支持

# HTTP/3的0-RTT特性可加速SSE连接建立
# 多路复用更高效,无队头阻塞问题

3. 标准化扩展

// 未来可能的标准扩展
// 1. 二进制数据支持
// 2. 压缩协议标准化
// 3. 服务质量分级

结论:被低估的协议瑰宝

SSE不是一个简单的"HTTP长连接hack",而是一个设计精巧、标准完备、生产就绪的服务器推送协议。它的核心优势在于:

  1. 标准合规:W3C正式推荐标准,所有现代浏览器原生支持

  2. 简单优雅:基于现有HTTP基础设施,无需额外端口或复杂握手

  3. 功能完备:自动重连、事件ID追踪、多事件类型等企业级功能

  4. 运维友好:使用标准HTTP端口,防火墙友好,监控工具兼容

在物联网数据推送、实时监控、新闻通知等服务器到客户端的单向数据流场景中,SSE往往是比WebSocket更简单、更合适的选择。它完美体现了"简单即是美"的设计哲学——用最小的协议创新,解决最广泛的实时通信需求。

下次当你需要实现服务器推送时,先别急着上WebSocket。问问自己:我真的需要双向通信吗?如果答案是否定的,那么SSE可能就是那个你一直在寻找的、优雅而高效的解决方案。