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 的复杂握手和协议升级。

在线人数统计功能

目标:实时向所有在线用户显示当前社区在线人数。
实现步骤

  1. 客户端发起 SSE 连接
    前端通过 new EventSource(‘/api/community/events?token=…’) 建立连接,并在 URL 中携带 JWT token 用于身份验证。
  2. 服务端接收连接并验证
    接口 streamCommunityEvents 解析 token,验证用户身份。
    设置 SSE 响应头,保持连接打开。
    生成唯一 clientId,将客户端信息(id、userId、response 对象)存入全局 clients Map 中(调用 addCommunityClient)。
  3. 广播当前在线人数
    addCommunityClient 内部调用 broadcastOnlineCount。
    broadcastOnlineCount 遍历 clients Map,向每个客户端发送 event: online 事件,数据为 { count: clients.size }。
  4. 维护心跳
    服务端每隔 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
    19
    graph 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

新帖实时推送功能

目标:当有新帖子发布并审核通过后,立即向所有在线用户推送通知。
实现步骤

  1. 用户发布帖子
    前端提交发帖表单,调用 createCommunityPost 接口。
    服务端进行内容验证、敏感词检查、权限判断,若通过且无需审核(status = 1),则帖子立即生效。
  2. 触发推送
    在帖子创建成功后,如果 status === 1 且 publish_status === 1,则调用 broadcastNewPost 函数。
    broadcastNewPost 遍历当前所有活跃客户端(clients Map),向每个客户端写入 event: new_post 事件,数据包含帖子 ID、标题、作者等关键信息。
  3. 客户端接收并展示
    前端 EventSource 监听 new_post 事件,提取数据后可在页面右上角或列表中动态显示“有新帖”的提示,或直接插入新帖卡片。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    graph 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,服务端验证后建立连接,确保安全性。