WebSocket 与轮询相比有哪些优势?适用于哪些业务场景?
解读
面试官问这道题,并不是想听“WebSocket 实时、轮询慢”这种一句话结论,而是考察候选人能否从“Android 端网络架构、电量、GC、线程模型、后台保活、弱网、运营商 NAT 超时、国内 ROM 定制”这些真实痛点出发,把技术差异量化成业务价值。答得越贴近国内环境(微信、钉钉、直播、手游、推送、厂商 Push 通道),越能体现资深度。
知识点
-
协议差异
轮询:HTTP/1.1 短连接,每次 TCP+TLS 握手,Request→Response 立即关闭,可缓存可压缩,但无状态。
WebSocket:HTTP/1.1 Upgrade 握手成功后切换到 TCP 全双工帧协议,头部仅 2~14 B,支持 Binary/Text、Ping/Pong、Close 帧。 -
安卓侧资源消耗
轮询:每次新建 TCP 连接→触发内核 wakeup→射频 Ramp-up→CPU 抢占→容易触发 16 ms 掉帧;频繁创建 OkHttp Call 对象造成 Young GC 抖动;AlarmManager 或 WorkManager 定时唤醒会加入系统耗电白名单统计,被厂商“一键省电”杀掉。
WebSocket:一次握手长连接,心跳包 2 B Ping 帧,射频可维持 Idle 态;OkHttp 内部复用 Socket,无额外对象;配合 Doze 模式可用前台 Service+低频率心跳(≥5 min)绕过厂商限制。 -
实时性与可靠性
轮询:受轮询间隔 T 限制,理论延迟 ∈[0,T],国内 4G/5G 下 T 一般≥30 s 才能省电;若采用长轮询(Comet),服务端 Hold 请求 20~60 s,遇 NAT 超时(移动 45 s、联通 60 s、电信 90 s)会被网关 RST,导致重连风暴。
WebSocket:服务端可立即推送,延迟百毫秒级;Ping/Pong 保活,在 NAT 超时前主动心跳,链路异常时客户端可感知 onFailure 立即重连,配合指数退避+重连风暴打散。 -
数据流量
轮询:每次 HTTP 头 500~800 B,空接口 1 kB 左右,30 s 轮询一天 2.8 MB;加鉴权 Cookie、SSL 握手膨胀更明显。
WebSocket:握手一次 1 kB,后续帧头 2 B,心跳 2 B,同等频率下流量降低 90% 以上。 -
安全与穿透
国内高校、政企办公网对 80/443 以外的端口封锁严格,WebSocket 走 443 可复用现有 HTTPS 基础设施,WSS 帧内可再封装 Protobuf+AES-GCM,满足等保/国密要求;轮询走 80/443 同样无穿透问题,但高并发时短连接造成 TIME_WAIT 端口耗尽,需要 LVS+NAT 层做回收。 -
服务端成本
轮询:短连接,无状态,可水平扩展,但 QPS 与用户数成正比,10 w 在线 30 s 轮询即 3.3 k QPS;WebSocket 长连接,需要内存保存 FD,10 w 在线≈2 GB 内存(Netty 4,单连接 20 KB),但 QPS 只与消息量有关,成本从“连接数”转向“消息数”。
答案
“在 Android 场景下,WebSocket 相比轮询的核心优势可以量化为:延迟从秒级降到百毫秒级;空载流量减少 90% 以上;射频唤醒次数降低两个数量级,整机待机时长提升 8%12%;GC 次数减少,卡顿帧率下降 12 fps;服务端 QPS 与在线时长解耦,节省 30% 以上带宽成本。
轮询的优势只有实现简单、无状态、穿透防火墙零配置,适合对实时性不敏感、调用量低频、后台可接受 15 min 延迟的场景,例如配置拉取、广告轮播、版本检查。
WebSocket 适用于:
- 即时通讯:微信、钉钉、客服聊天,需支持 @ 消息、已读回执、多端漫游。
- 直播互动:弹幕、点赞、礼物,峰值 50 w 条/秒,需要二进制 Protobuf 帧压缩。
- 金融行情:股票、期货、数字货币,推送频率 1~5 次/秒,丢包即补帧,客户端本地插值。
- 多人在线游戏:帧同步、状态广播,对延迟<100 ms 且需要后台保活,需搭配 ForegroundService+WiFi 锁。
- IoT 控制:智能家居、车载 T-Box,指令下行需立即唤醒设备,结合 MQTTS over WebSocket 穿透家庭路由器。
- 远程日志/调试:开发者模式下实时日志回捞,用 WSS+OAuth2 一次性 Token,避免长轮询造成的 CPU 采样失真。
在国内实际落地时,还要叠加厂商省电策略:心跳间隔必须大于 5 min 才能进入 Doze whitelist;应用退到后台 1 min 后,WebSocket 会被厂商冻结,需降级融合推送(小米、华为、OPPO 通道)做兜底,确保 IM 消息必达。”
拓展思考
- 混合通道策略:如何把 WebSocket、厂商 Push、轮询三种通道做成优先级降级树?请设计一套状态机:活跃前台→WebSocket;后台 0
1 min→WebSocket+心跳;15 min→厂商 Push 透传;5 min 后→轮询拉取离线消息。 - 弱网优化:在地铁、电梯场景,RTT 突然涨到 2 s、丢包 20%,如何动态调整心跳间隔与重连退避?可结合 Android 的 ConnectivityManager.getLinkProperties() 获取 DNS 类型(DNS-over-TLS/DNS-over-HTTPS)判断网络质量,再用自适应心跳算法(Exponential weighted moving average)。
- 安全合规:国内金融类 App 要求“国密 SM4+SM2”端到端加密,WebSocket 帧如何在 JNI 层调用 TEE 的 soter 接口完成 SM2 签名,而不把私钥导入用户空间?
- 流量统计:Android 10 以后引入 TrafficStats.tagSocket() 与 NetworkStatsManager,如何把 WebSocket 长连接流量归属到应用自身,避免被系统计入“热点共享”导致用户投诉?
- 替代方案评估:如果业务只是订单状态变更(外卖、打车),用 Server-Sent Events(SSE)是否比 WebSocket 更省内存?请从 OkHttp 事件循环、Chunked 编码、NAT 超时、中文乱码四个维度对比。