在 Web 开发中,一个常见的问题是:既然 WebSocket 能实现双向实时通信,为什么大部分网站仍然在用普通的 HTTP 请求?
甚至有人会问:能不能把所有接口都换成 WebSocket,这样既快又省事?
答案很明确:能,但不值。
技术选型不是选"最强的",而是选"最合适"的。本文用 "打电话" 这个最简单的比喻,帮你彻底看懂四种交互方式的成本------你只需要搞清楚:这条电话线,占多久?

一、先搞懂"打电话"------后面全通了
- TCP 连接 = 一条电话线。你家和服务器之间能同时通多少条线,是有上限的(文件描述符限制)。
- HTTP 短连接 = 说完就挂。拨号 → 说话 → 挂断。下次再说,重新拨号。
- keep-alive = 说完不挂,但也不说话。线还连着,可以马上说下一句,但双方都知道"现在没通话"。
- WebSocket / SSE = 电话从不挂断。24 小时占着线,随时可以说话(单向或双向)。
- HTTP/2 = 一线多话。一根电话线上可以同时传好多路通话,占着线,但不占'坑位'了。
- 浏览器连接数限制 = 你家电信局规定:同一个网站最多同时占 6 条线(HTTP/1.1)。
所有代价,都来自"这条线占多久"。

二、四种交互方式,一张表看懂
| 方式 | 电话线怎么用 | 谁主动说话 | 典型场景 |
|---|---|---|---|
| HTTP 短连接 | 拨号 → 说话 → 挂断,每次重拨 | 浏览器 → 服务器 | 大部分 Web 页面、API |
| 轮询 | 反复拨号、挂断,每几秒一次 | 浏览器 → 服务器 | 小规模、低频次查询 |
| 长轮询 | 拨号后不挂,等服务器说话,说完挂 | 浏览器 → 服务器 | 兼容老浏览器的推送 |
| SSE | 拨通后永不挂断,服务器单向喊话 | 服务器 → 浏览器 | 实时通知、股票行情 |
| WebSocket | 拨通后永不挂断,双向随时说话 | 双向 | 聊天、游戏、协同编辑 |

HTTP 短连接:说完就挂,线即用即还
它是怎么用电话线的?
你想查商品列表。浏览器拿起电话拨号(TCP 三次握手),接通后说"我要查列表"(HTTP 请求),服务器说"给你数据"(HTTP 响应),然后立刻挂断 。
线空出来了,别人可以打。
哪怕开了"说完不挂"模式(keep-alive),线还连着,但双方都知道这通电话已经说完了 ,只是等着你说下一句。
下一句来了,还是"我要查另一个东西",说完又等。
关键:这条线没有被"专享"------它只是短暂借用,绝大部分时间是空闲、可以被其他人复用的。
为什么它能撑住十万人同时访问?
不是线多,是每个人占线的时间极短 。
你家同时只能接 1000 通电话(并发连接),但一秒钟可以处理 1 万通(QPS),因为每通只说 0.1 秒就挂。
十万人是分时说话的,不是十万人同时占着线。

缺点
- 服务器不能主动打电话给浏览器。
- 每通电话都要说一遍"我是谁、我要什么"(HTTP 头部开销)。
- 想实时知道服务器那边的新消息?不行,你得自己不停打过去问。
所以,绝大多数"查东西、填表单"的业务,用"说完就挂"的电话就够了。
你的商品列表、文章详情、提交订单------全是这样。
轮询:反复拨号问"有消息吗",99% 白打
有人想:"我要实时知道服务器有没有新消息。"
最简单的办法:每隔几秒拨一次电话。
拨通:"有消息吗?"
服务器:"没。"挂断。
10 秒后,再拨:"有消息吗?""没。"挂断。
......
这 100 通电话里,99 通都只换来一个"没"字。
假设 10 万用户,每 10 秒拨一次:
- 服务器一秒钟要接 1 万通电话(QPS 10,000)
- 一天 8.64 亿通
- 99% 的电话内容都是"有消息吗?""没。"
你只是想让服务器在有消息时通知你,结果服务器 99% 的时间在接空电话。
电话线资源、服务器精力、带宽流量------全浪费了。

所以轮询只适合两种场景:
- 人极少(百人级内部系统)
- 只打一小会儿(支付结果,几十秒就停)
大规模、长时间轮询,是电话费灾难。

SSE:电话从不挂断,只等服务器喊你
那不要轮询了,我直接打通电话,不挂,等服务器主动喊我 。
这就是 SSE。
它是怎么用电话线的?
浏览器拨号,接通后说:"我要一条专线,有消息你就直接喊我,我不挂。"
服务器说"好",然后把这条线记住是"待呼专线" 。
这条线从此被占住了------服务器不能把它给别人用,浏览器也不能用它打给别人。
数据变了,服务器拿起这条线喊一声"刷新!"浏览器收到,线还连着,继续等。
这条线占多久? 用户关页面才挂。几小时,甚至一整天。

代价是什么?
你家的电话线插槽是有限的(文件描述符上限)。
每条从不挂断的电话占一个插槽,10 万条这样的电话,你家得有 10 万个插槽------操作系统默认只有 1024,调大也有限。

⚠️ 这里有个隐形巨坑:浏览器的"限号"政策
很多人想:既然 SSE 这么好,我给页面上每个组件(订单、消息、天气、好友列表)都拉一根 SSE 专线行不行?
不行,你会发现网页直接"卡死"了。浏览器自己有个硬性规定:同一个域名,最多只能同时开 6 条电话线。
- 如果你开了 6 个 SSE 专线,这 6 条线就把"名额"占满了。
- 此时你再去点"提交订单"或者"加载图片",浏览器会发现:没线了!
- 结果:你的订单请求排在后面死等,用户看到的就是转圈圈,直到你关掉一个 SSE 标签页。
这就是为什么现在做实时推送,一定要配上 HTTP/2(一线多话): 它能让几十路通话挤在同一条物理线里,否则你的长连接越多,你的网站崩得越快。
WebSocket:双向永不挂断,更贵,但更快
SSE 是服务器单向喊浏览器。
如果你需要浏览器也能随时喊服务器,比如发弹幕、抢购、打游戏------那就得上 WebSocket。
它和 SSE 一样:一条永不挂断的电话,长期占一个插槽。
双向随时说话意味着双向解析、心跳保活、断线重连,服务器维护成本比 SSE 高出一截。
所以,WebSocket 不是"更好的 HTTP",它是双向永不挂断的专线 ------
只有当你真的需要两边随时喊话时,才值得付这个专线费。

抢购和弹幕:为什么它们非用"永不挂断"不可?
你可能会问:你把 WebSocket 说得这么贵,那直播间弹幕、电商秒杀------它们怎么全在用?不怕代价吗?
因为它们没有别的选择。
抢购:半秒钟,线已通 vs 现拨号
主播喊"3、2、1,上链接"。
你用 SSE 单向专线------没问题,服务器喊你"开抢了!"这一步极快。
但问题来了:你收到喊话后,要立刻发一个"我要抢购"的命令给服务器 。
SSE 专线是单向的,你不能用它发命令。你只能重新拨一次电话(HTTP 请求)。
重新拨电话要做什么?
- 如果这条线是现拨的:拨号音、等待接通(三次握手 + TLS),几十上百毫秒。
- 如果复用了 keep-alive 线:省了拨号,但你还是要说一遍"我是谁、我要抢购",服务器听完,处理完,挂断。
这一来一回,几百毫秒就出去了。 不是服务器处理慢,是现拨电话、现说话这套流程本身就重。
WebSocket 双向专线呢?
线一直通着,嘴一直对着话筒。 你直接说"我要抢购!"服务器直接回"抢到了!"
没有拨号音,没有"我是谁",没有挂断重来。
这半秒的差距,就是"线已经通了"和"现拨号"的差距。
秒杀场景里,半秒足够让库存从 100 变 0。

弹幕:高频喊话,专线省下无数重拨
直播间几万人,每人每秒发一条弹幕、收几十条弹幕。
如果用轮询:每人每秒拨一次电话问"有新弹幕吗?"
几万人就是几万通/秒,99% 的电话内容都是"没有新弹幕"。
服务器累死,线也占死。
WebSocket 双向专线:每人只拨一次,线一直通着 。
弹幕数据像流水一样在线里双向流动,没有挂断重拨,没有空问询。
它们付"永不挂断"的代价,因为账算得过来:
- 抢购:慢半秒,丢一单,客单价 200 块------专线费比丢单便宜。
- 弹幕:卡半秒,用户关直播------流量和打赏比专线费贵。
在这些场景里,"永不挂断"的"贵"不再是代价,是必须交的保护费。

你的业务:值不值得打这通"永不挂断"的电话?
你的业务里,有多少处"半秒生死线"?
- 查列表、点详情、提交表单:慢 1 秒,用户抱怨,但不会跑。
- 刷资讯、看视频:慢 2 秒,用户等,等到了就行。
- 后台管理、数据大屏:慢 3 秒,用户喝口茶,回来数据有了。
这些场景,"说完就挂"的电话完全够用。
不需要 24 小时占着线,不需要占着服务器一个插槽。
你的用户,真的值得你为他打一通永不挂断的电话吗?

选型决策:一张流程图就够了
需要服务器主动打电话给浏览器吗?
├─ 否 → 用"说完就挂"的电话(HTTP 短连接),省线省钱
└─ 是 →
├─ 只需要服务器→浏览器,浏览器不用打回去?
│ ├─ 是 → SSE 单向专线(永不挂断,轻量)
│ └─ 否 → 需要双向随时说话 → WebSocket 双向专线(永不挂断,更重)
│
└─ 额外考量:
├─ 用户极少或只打一小会儿 → 轮询(反复拨挂,别大规模)
├─ 未来明确要双向说话 → 直接拉 WebSocket 双向专线,省一次布线
└─ 内部工具、单机部署 → 全拉专线也不是不行
最后几句
技术选型不是选"最强的",是选"总电话费最低的"。
"说完就挂"的电话不酷,但它不占线、不占槽位 ,撑起整个互联网的日常通信。
SSE 单向专线不显眼,但它刚刚好解决了"服务器主动喊浏览器"的需求,长期占一条线,但成本可控 。
WebSocket 双向专线很酷,但它的代价是为每个用户长期占着一条电话线、一个插槽------只有双向高频、半秒生死的业务,才真的值。
把对的通话模式,用在对的地方,才是真本事。
别再纠结"为什么不都用 WebSocket 专线"了。
先问问自己:我的业务,真的需要为每个用户打一通永不挂断的电话吗?
