实时通信
HTTP
HTTPS 是 HTTP 的安全版本,在 HTTP 和 TCP 之间加入了 SSL/TLS 加密层,保证:
HTTPS作为一个加密层,可以与所有版本的HTTP结合使用
加密:防止数据被窃听。
完整性:防止数据被篡改。
身份验证:验证服务器身份(通过证书)。
在生产环境中,务必使用 HTTPS 保护用户数据(如密码、Token)
协议是:浏览器 ↔ 服务器 每次建立连接时「自动协商」出来的,它是灵活、动态、可同时支持多种的
HTTP协议版本并不是一个网站(域名)固定不变的,而是动态协商、灵活多变的。它既不是绑定在域名上,也不是根据具体的接口(URL路径)来定,而是由客户端(浏览器)和服务器在连接建立时共同协商决定的。同一个域名下的不同请求,甚至在不同时间、不同网络环境下,完全可能使用不同的HTTP版本。HTTP协议的设计目标之一是向后兼容和平滑升级
HTTP版本进阶
HTTP/1.0:每个请求/响应后关闭连接。
HTTP/1.1:引入持久连接(Keep-Alive)、管道化(Pipelining)、Host 头等
HTTP/2:二进制分帧、多路复用、头部压缩,大幅提升性能。(基于TLS的ALPN)
HTTP/3:基于 QUIC(UDP),减少连接延迟,提高弱网环境表现(基于Alt-Svc)
在Network面板里随便点开一个请求,看看它的 Alt-Svc 头。如果看到了,就说明这个网站已经为你准备好了更快的HTTP/3连接
HTTP 协议不是绑定域名,也不是绑定接口
是浏览器和服务器「每次连接自动协商」的
服务器可以同时开多种协议,自动兼容
对前端开发者来说:基本不用管,自动适配
HTTP 轮询
信道(Channel):在网络通信中,通常指一个TCP连接。每个TCP连接都会占用服务器端的文件描述符、内存等资源。并发连接数过高可能导致服务器资源耗尽。
HTTP 轮询是一种基于传统 HTTP 请求-响应模式的伪实时通信技术
短轮询:客户端按照一定的时间间隔,反复向服务器发送 HTTP 请求,询问是否有新数据,服务器收到请求后立即返回响应。
长轮询:服务器接收到请求后,如果没有新数据,会保持连接挂起,直到有新数据或超时才返回,这可以减少无效响应。
实时性低,长轮训较高一点;资源消耗短轮询较高,长轮训较低
短轮询虽然对并发连接数友好,但它会带来巨大的请求频率,适合客户端数量不大的场景
长轮询的每个请求都会长期占用一个连接,不利于高并发
例子:网页扫描二维码
SSE
Server-Sent Events 是一种允许服务器主动向浏览器推送事件的技术。它基于纯 HTTP 协议,客户端通过 EventSource API 建立连接,服务器保持连接打开,并以特定格式 (text/event-stream) 发送数据。SSE 具有以下特点:
- 单向通信:仅服务器可推送数据,客户端不能通过该连接发送数据(适合通知类场景)。
- 自动重连:连接断开后浏览器会自动尝试重新连接。
- 轻量简单:无需 WebSocket 的复杂握手和协议升级。
在线人数统计功能
目标:实时向所有在线用户显示当前社区在线人数。
实现步骤
- 客户端发起 SSE 连接
前端通过 new EventSource(‘/api/community/events?token=…’) 建立连接,并在 URL 中携带 JWT token 用于身份验证。 - 服务端接收连接并验证
接口 streamCommunityEvents 解析 token,验证用户身份。
设置 SSE 响应头,保持连接打开。
生成唯一 clientId,将客户端信息(id、userId、response 对象)存入全局 clients Map 中(调用 addCommunityClient)。 - 广播当前在线人数
addCommunityClient 内部调用 broadcastOnlineCount。
broadcastOnlineCount 遍历 clients Map,向每个客户端发送 event: online 事件,数据为 { count: clients.size }。 - 维护心跳
服务端每隔 20 秒向每个客户端发送注释行 :keep-alive\n\n,防止代理或浏览器因长时间无数据而超时关闭连接。
客户端断开处理
当客户端关闭页面或网络中断时,触发 res 对象的 close 事件。
在 close 回调中清理心跳定时器,并调用 removeCommunityClient(clientId) 从 clients Map 中移除该客户端。
removeCommunityClient 再次触发 broadcastOnlineCount,更新所有客户端的在线人数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19graph TD
A[客户端打开社区页面] --> B[创建 EventSource 连接]
B --> C[服务端接收 /events 请求]
C --> D{验证 token}
D -- 无效 --> E[返回 401]
D -- 有效 --> F[设置 SSE 响应头]
F --> G[生成 clientId, 存入 clients Map]
G --> H[调用 broadcastOnlineCount]
H --> I[遍历 clients, 发送 online 事件]
I --> J[启动心跳定时器]
J --> K[客户端接收 online 事件, 更新在线人数]
K --> L{客户端断开?}
L -- 是 --> M[触发 close 事件]
M --> N[清除心跳, 调用 removeCommunityClient]
N --> O[从 clients 删除该 client]
O --> P[再次 broadcastOnlineCount]
P --> Q[其他客户端收到更新后在线人数减1]
L -- 否 --> K
新帖实时推送功能
目标:当有新帖子发布并审核通过后,立即向所有在线用户推送通知。
实现步骤
- 用户发布帖子
前端提交发帖表单,调用 createCommunityPost 接口。
服务端进行内容验证、敏感词检查、权限判断,若通过且无需审核(status = 1),则帖子立即生效。 - 触发推送
在帖子创建成功后,如果 status === 1 且 publish_status === 1,则调用 broadcastNewPost 函数。
broadcastNewPost 遍历当前所有活跃客户端(clients Map),向每个客户端写入 event: new_post 事件,数据包含帖子 ID、标题、作者等关键信息。 - 客户端接收并展示
前端 EventSource 监听 new_post 事件,提取数据后可在页面右上角或列表中动态显示“有新帖”的提示,或直接插入新帖卡片。1
2
3
4
5
6
7
8
9
10graph TD
A[用户提交发帖] --> B[服务端 createCommunityPost]
B --> C{验证与审核通过?}
C -- 否 --> D[返回结果, 不推送]
C -- 是 --> E[帖子保存成功, status=1]
E --> F[调用 broadcastNewPost]
F --> G[遍历 clients Map]
G --> H[对每个客户端发送 new_post 事件]
H --> I[客户端监听 new_post 事件]
I --> J[前端更新 UI, 显示新帖通知]
关键技术点总结
技术点 说明
SSE 连接管理 使用 Map 存储所有活跃连接,key 为唯一 ID,value 为包含 res 对象的 client 信息。
广播机制 遍历 Map,通过每个 client 的 res.write() 发送格式化消息。
心跳维持 定时发送注释行,防止连接因空闲被关闭。
连接清理 监听 res.on(‘close’) 事件,及时移除断开的客户端,并更新在线人数。
事件格式 event: 事件名\n + data: JSON字符串\n\n,符合 SSE 规范。
身份验证 连接 URL 中携带 JWT token,服务端验证后建立连接,确保安全性。




