欢迎光临
我们一直在努力

Web 数据交互选型指南:为什么不都用 WebSocket?——技术版

在 Web 开发中,一个常见的问题是:既然 WebSocket 能实现双向实时通信,为什么大部分网站仍然在用普通的 HTTP 请求?
甚至有人会问:能不能把所有接口都换成 WebSocket,这样既快又省事?

答案很明确:能,但不值。
技术选型不是选“最强的”,而是选“最合适”的。本文将带你系统梳理四种主流数据交互方式——HTTP 短连接、轮询、Server-Sent Events(SSE)、WebSocket,分析它们的成本、收益和适用场景,帮你做出合理决策。


一、四种交互方式,一张表看懂

方式连接模型通信方向状态典型场景
HTTP 短连接 请求→响应后断开 客户端主动 无状态 大部分 Web 页面、API
轮询 定期发起 HTTP 请求 客户端主动 无状态 小规模、低频次查询
长轮询 挂起请求,有数据再响应 客户端主动 无状态 兼容老浏览器的推送
SSE 单行长连接 服务端单向推送 有状态 实时通知、股票行情
WebSocket 全双工长连接 双向实时 有状态 聊天、游戏、协同编辑

长轮询是轮询的优化版本,但本质仍是 HTTP 请求-响应模式,本文重点比较其他四种。


HTTP 短连接:Web 的基石,不酷但稳

原理:客户端发起请求,服务器处理后返回响应,连接随即关闭。下一次请求再次建立新连接。

它笨吗?笨。但它有一个其他协议永远追不上的优势:用完即走。

服务器不需要记住你。
你发一个请求,服务器处理完,就把你忘了。连接归还给连接池,内存清空,文件描述符释放。下个请求来了,重新来过。

这套机制笨拙,但它让 Web 拥有了无限伸缩的能力。十万人同时访问,对服务器来说只是“每秒处理了多少个请求”,而不是“同时维护着多少条专线”。HTTP 服务器可以随时重启、随时扩缩容,新机器和老机器一模一样,请求打到谁都能处理。

这就是无状态的红利。你不需要为“记住用户”付任何账单。

再加上生态成熟:CDN 缓存、负载均衡、监控告警、重试幂等,全是开箱即用。你写个接口,挂个 Nginx,就能撑住百万并发。这不是技术多强,是生态红利。

缺点

  • 服务端无法主动推送数据
  • 每次请求携带重复的头部信息,有一定开销
  • 实时性差,必须由客户端触发

所以,绝大多数读多写少、无需实时推送的业务,HTTP 短连接就是成本最低、最省心的方案。你的商品列表、文章详情、表单提交,全用 HTTP,完全没问题。


轮询:看起来简单,其实是隐形巨坑

有人说:“我不想要短连接,我想让服务器主动告诉我数据变了。”那最简单的办法是什么?轮询。

客户端每隔几秒发一次请求,问服务器:“数据变了吗?”服务器每次都说:“没变。”——这就是轮询。

它简单,但它贵。贵到你想象不到。

我们来算笔账。假设你有 10 万在线用户,每人每 10 秒轮询一次列表接口:

  • QPS = 100,000 ÷ 10 = 10,000
  • 日均请求量 = 10,000 × 86,400 = 8.64 亿次

这 8.64 亿次请求里,99% 的响应都是“数据无变化”。

你付出的成本包括:

  • 用户的手机电量、流量
  • 运营商的带宽费用
  • 你的网关、Nginx、后端、数据库连接池的无效消耗
  • 监控、日志、告警系统的写入压力

你只是想要个“数据变动时通知我一下”,结果却让整个系统为“没变动”支付了 99 倍的成本。

所以轮询只有两个适用场景: 一是用户量极小(百人级内部系统),二是短期行为(比如支付结果轮询,轮个几十秒就停了)。大规模 + 长时间停留 + 轮询 = 技术灾难。


SSE:单向推送,比 WebSocket 轻得多

那不要轮询了,搞个长连接行不行?可以,但不一定非要 WebSocket。

如果你只需要服务器给客户端推消息,客户端不需要通过同一个连接发数据回去,那 SSE(Server-Sent Events) 是更好的选择。

SSE 是什么?就是浏览器原生支持的 EventSource API,客户端发起一个 HTTP 请求,服务器不关连接,有数据了就往这个连接里写一行文本。就这么简单。

实战用法:长列表自动刷新

用户盯着订单列表、监控大屏、后台工单——数据偶尔变,但用户几乎不点发送。这种场景下,SSE 是真正的“神兵利器”:

  • 浏览器发起一个 SSE 连接,等在那儿。
  • 后端发现数据变了(比如数据库触发器发了个 Redis 消息),就往这个连接里写一行 data: refresh。
  • 前端收到消息,静默调用一次普通的 HTTP 接口,把列表重拉一遍。
  • 用户看起来页面自动刷新了,但你付出的成本只是:

    • 一个 HTTP 长连接(比 WebSocket 轻得多,不需要处理二进制帧、心跳保活)
    • 数据变动时才推一个极短的消息
    • 然后一次普通的 HTTP 查询(走缓存,几乎无感)

    这套组合拳,才是大多数“盯着看”场景的最优解。 你为了收个通知,修一条昂贵的双向高速路,还得自己维护,完全没必要。

    一个绕不开的现实问题:浏览器连接数限制

    讲到这里,必须提醒一个非常容易踩的坑:浏览器对长连接的数量是有限制的。

    在老旧的 HTTP/1.1 协议下,同一个域名最多同时开 6 个长连接。如果用户是个“标签页狂魔”,一口气开了 10 个你的系统页面,第 7 个标签页可能就收不到推送了——不是你的服务器不行,是浏览器不让连了。

    这也是为什么很长一段时间,大型 Web 应用不敢大规模用长连接的原因。

    解决方案也很直接:上 HTTP/2。 HTTP/2 的多路复用技术,允许所有长连接共享同一个 TCP 管道,不再有 6 个的限制。你现在看那些能稳定跑 SSE 或 WebSocket 的大型网站,几乎都配了 HTTP/2。

    所以,如果你打算在生产环境用长连接,先把 HTTP/2 开起来,否则迟早踩坑。


    WebSocket:双向实时,但代价不小

    好,如果你说:“我不但要收数据,还要通过同一个连接频繁发数据,比如聊天、游戏、协同编辑。”那 SSE 就不行了,得上 WebSocket。

    WebSocket 的核心优势只有两个,但都很硬:

  • 服务器可以主动发消息(SSE 也能做到)
  • 双向通信(SSE 做不到,客户端要发数据必须另起 HTTP 请求)
  • 但它的代价也在这:

    第一,服务器必须记住你。
    每一个 WebSocket 连接,服务器都要占用一块内存、占着一个文件描述符。10 万条连接,就是 10 万个活着的对象。这不只是数字,是实实在在的 GC 压力、OOM 风险、系统文件描述符上限的拉扯。

    HTTP 的连接是借来的,用完就还。WebSocket 的连接是专线,你占着,别人就不能用。

    第二,不好扩展。
    HTTP 扩展是靠加机器,新机器和老机器一样,请求打过来谁都能处理。
    WebSocket 扩展是连人带椅子一起搬。你加一台新机器,得想办法把老机器上的用户「迁」过去——要么让客户端重连(踢用户下线),要么做全局路由层(每发一条消息都要问 Redis「这个用户现在坐哪台机器」)。

    这不是不能扩展,是扩展的成本比 HTTP 高一个量级。

    第三,协议生态弱。
    HTTP 可以随便挂 CDN、随便负载均衡,WebSocket 不行。CDN 不缓存,负载均衡要单独处理 sticky session 或统一路由。心跳保活、断线重连、鉴权续期、请求响应配对……HTTP 帮你做好的事,WebSocket 全得自己写。

    所以,WebSocket 从来不是“更好”的 HTTP,它是一个专门解决“双向高频通信”问题的特种工具。


    游戏、抢购、直播弹幕为什么必须用长连接?

    你可能还是会疑惑:你前面把 WebSocket 说得这么“贵”,那直播间弹幕、电商秒杀、多人在线游戏——它们怎么全在用?不怕代价大吗?

    因为它们没有别的选择。

    这类场景对延迟的敏感是“会死人”的。我拿抢购给你拆半秒钟,你就明白了。

    抢购:半秒钟的生死线

    假设主播喊“3、2、1,上链接”。你用了 SSE 收通知——这一步没问题,延迟很低。但问题出在下一步:你收到通知后,得发一个 HTTP POST 请求去抢购。

    这个 HTTP 请求干了什么?

    • 如果是新连接:TCP 三次握手,1.5 个 RTT(往返时间)。
    • 如果是复用连接:省了握手,但 HTTP 头部依然几百字节,Cookie、User-Agent、鉴权 Token 全塞进去,服务器解析也要时间。
    • 服务器处理完,再回一个同样沉重的响应头。

    这一来一回,几百毫秒就出去了。 不是业务逻辑慢,是 HTTP 这套“繁文缛节”本身就重。

    那 WebSocket 呢?

    连接在用户进直播间时就建好了,一直“热”着。发抢购指令时:

    • 没有握手,路早就铺好了。
    • 消息头极小,WebSocket 帧头部只有 2-14 字节,发一个 { "action": "buy", "id": 123 } 几乎是瞬间到达。
    • 双工直达,服务器扣完库存,顺着同一条连接就把结果扔回来了。

    这半秒的差距,就是“连接冷启动”和“连接热启动”的差距。 在秒杀场景里,半秒足够让库存从“有”变“无”,足够让用户骂你“垃圾服务器”。

    直播弹幕:高频小包的生态位

    再看弹幕。直播间几万人同时发、同时收弹幕。

    如果用 HTTP 轮询:每人每秒发一条弹幕、拉一次弹幕列表,光头部开销就能把带宽打满。而且 HTTP 是“发一条、等一条”,用户发完弹幕要等服务器响应才知道有没有发成功,体验卡顿。

    WebSocket 在这里的胜出,不是因为“双向”,而是因为极低的开销。每条消息省下几百字节头部,几万人高频发,省下来的带宽和 CPU 是实打实的钱。

    所以,它们为什么敢付这个代价?

    因为这笔账算得过来。

    • 抢购业务:慢半秒,流失一单,客单价 200 块,服务器成本再高也高不过丢单的损失。
    • 弹幕业务:卡半秒,用户刷不动,直接关直播间,流量和打赏全没了。
    • 游戏业务:延迟高 20ms,对枪对不过,玩家流失,这是要命的。

    在这些场景里,WebSocket 的“代价”不再是代价,而是必须交的保护费。 它换来的是极低延迟、极高频次、双向自由的通信能力,这是 HTTP 给不了的。


    你的业务为什么不用全站 WebSocket?

    很简单:你的业务里,有多少处“半秒生死线”?你的业务,值得让服务器为每个用户多占一块连接内存吗?

    • 查列表、点详情、提交表单:慢 1 秒,用户抱怨,但不会跑。
    • 刷资讯、看视频:慢 2
      秒,用户等,但等到了就行。
    • 后台管理、数据大屏:慢 3 秒,用户喝口茶,回来数据有了。

    这些场景,HTTP 不需要记住你是谁,处理完请求就把你忘了。
    你不值得让服务器为你占着那条专线。

    HTTP 足够用,轮询坑人但有人踩过坑后会换 SSE,SSE 轻量够用——为什么要多花几倍的成本去养几十万条长连接、自己写心跳重连、处理分布式状态?


    选型决策:一张流程图就够了

    你可以用下面的逻辑来决定当前场景用什么技术:

    需要服务端主动推送数据吗?
    ├─ 否 → 用 HTTP 短连接(REST/GraphQL),省心省钱
    └─ 是 →
    ├─ 只需要服务端→客户端,客户端不用发数据?
    │ ├─ 是 → SSE,轻量原生,优先选
    │ └─ 否 → 需要双向实时 → WebSocket

    └─ 额外考量:
    ├─ 用户量极小或短期行为 → 轮询也可,但别上规模
    ├─ 未来明确要双向能力 → 直接上 WebSocket,省一次重构
    └─ 内部工具、单机部署 → 全 WebSocket 也不是不行


    最后几句

    技术选型不是选最强的,是选总成本最低的。

    HTTP 短连接不酷,但它省事、成熟,撑起整个互联网。
    SSE 不显眼,但它刚刚好解决了“服务端推送”的大部分需求,不用多做一件事。
    WebSocket 很酷,但它的成本是“维护状态 + 生态薄弱 + 自己补功能”,只有在你真正需要双向高频实时通信时,才真的值。

    把对的协议用在对的地方,才是真本事。
    别再纠结“为什么不都用 WebSocket”了,先问问自己:我的业务,真的需要那条双向高速路吗?

    赞(0)
    未经允许不得转载:171主机测评 » Web 数据交互选型指南:为什么不都用 WebSocket?——技术版
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址