面试官微微一笑:“你平时用微信吧?能讲讲那个‘对方正在输入…’功能,如果是你来做,底层架构会怎么设计吗?

图片

这小老弟心想,这题我熟啊,脱口而出:“这简单!两边客户端起个 WebSocket 长连接,只要 A 的键盘一动,就给服务端发个消息,服务端再透传给 B。齐活!”

面试官听完没说话,喝了口水反问:“微信十几亿日活,每天晚高峰大家都在激情对线。要是每个人每敲一个字母,客户端就发一个网络请求,你算过这个并发量吗?你信不信按你这个方案,今晚网关服务器就得物理冒烟?”

小老弟瞬间哑火。

其实,这道题根本不是在考你懂不懂 WebSocket,它是一道披着前端外衣的“高并发流量削峰 + 极限状态同步”的顶级架构题。今天,咱们就带你拆解一下,看看国民级 APP 是怎么用“四两拨千斤”的骚操作,把海量并发化解于无形的。


第一层心法:别拿技术硬刚,用“产品规则”物理超度流量

很多程序员的通病是:一上来就想着用 Kafka、用 Redis 集群去硬抗并发。但真正顶级的架构师,第一步绝对是和产品经理“拉扯”

在微信里,最让人心跳加速的,就是顶端闪烁的“对方正在输入...”。但你要知道,这玩意儿能扛住十几亿人的折腾,最大的功劳在于它暗藏的“变态级”产品红线。

微信官方揭秘过,触发这个功能,必须同时满足两个极其苛刻的条件:

  1. 10秒黄金法则:你发出消息后,对方必须在 10秒内 打开对话框。

  2. 动作感:对方打开了,且还在输入框里打了字(哪怕只是打个空格)。

看懂了吗?如果你发了消息,对方对着屏幕发呆了半分钟才开始回,抱歉,服务器压根不伺候,你这边什么都看不到。

图片

通过这套极其克制的业务规则,微信把一个原本可能是百亿 QPS 的灾难级动作,硬生生降维成了一个低频的偶发事件。90% 的无效网络请求,在客户端就被直接“物理超度”了。


第二层心法:抛弃长连接,拥抱“信令握手”与指挥塔模式

好了,现在 A 满足了 10 秒法则,终于开始打字了。是不是就开始用长连接狂发数据了?

大错特错。 官方明确说过:微信聊天并非时刻连接,而是采用了一套高效的“对讲机指挥塔”模式。

专业术语叫:信令握手(Signaling Handshake)

什么意思呢?为了极致省电和省流量,大厂是绝对不会让你的手机时刻处于高频数据传输状态的。

  1. 申请频道: 当 A 开始输入,A 的微信就像拿起对讲机,向指挥塔(微信服务器)发送一个极小极轻量的状态信令(申请临时私密频道)。而且客户端内置了状态机防抖,短时间内怎么狂敲键盘,都只发一次。

  2. 查户口(丢弃逻辑): 服务器收到这个信令后,绝不盲目转发!它会立刻去高性能缓存(比如 Redis,或者网关节点的 Local Cache)里查 B 的底细:“B 此时此刻在线吗?B 的当前活跃窗口是 A 吗?”

  3. 精准打击: 如果 B 正在刷朋友圈,服务器二话不说,直接在内存里把这个信令丢进垃圾桶。只有确认 B 正在眼巴巴地盯着和 A 的聊天框,服务器才会把“A已准备回话”的信号透传给 B。

图片

这就是为什么你和别人聊天时,“正在输入”会时有时无——因为你们之间的信令通道不是永远粘连的,而是在反复地进行轻量级握手与断开。服务端在这里扮演的是一个“无情的太极大师”,主打一个能不转发就不转发


第三层心法:那些“不显示”的边缘场景,才是架构师的修罗场

面试官往往会在这时候给你下套:“那你知道有哪些情况,明明在打字,但就是不显示吗?”

如果你能把下面这几个异常边界场景(Edge Cases)甩在面试官脸上,这 Offer 基本就稳了:

  • PC 端微信不触发: 为什么?因为 PC 端经常是键盘盲打、多窗口并发。如果全量同步状态,无效信令极多,并且彻底失去了移动端“面对面对讲机”的特定语境。

  • 表情包不触发: 斗图时发表情包是单次点击触发,不存在“持续输入”的过程,直接走消息下发通道,根本不触碰信令层。

  • 输入法缓冲池盲区: 如果对方在第三方输入法里“打了删,删了打”,只要他没把字真正上屏(进入微信的输入框组件),微信是无法捕获 keystroke 事件的,你自然什么都看不到。


第四层心法:去中心化自毁,破解弱网卡死之局

这是整个设计的“封神”之笔。

面试官最后的一击:“如果 A 触发了状态,B 的手机上也显示了‘正在输入’。这时候 A 突然拿着手机进了电梯,彻底断网了,没法发‘我输入完了’的信号。B 的屏幕是不是就永远卡死在‘正在输入’上了?”

如果你答“服务器用心跳包检测,掉线了再通知 B”,那你就太嫩了,太耗费服务器资源了!

满分答案是:客户端本地定时自毁机制。

B 的客户端在收到“正在输入”的信令时,压根不需要服务器来告诉它什么时候结束。客户端自己会默默启动一个 5秒的倒计时

  • 如果在这 5 秒内,A 把消息发过来了,新消息直接覆盖,提示平滑消失。

  • 如果过了 5 秒,A 还是没动静(不管他是进电梯断网了,还是在思考人生),B 的客户端就会强制自己把提示隐藏掉

这种“单向信令下推 + 本地定时自毁”的设计,既完美解决了弱网状态卡死的问题,又省掉了 A 端续期状态的大量带宽成本。


面试标准答案模板(直接套用,惊艳面试官)

“设计微信的‘正在输入’功能,其核心本质不是技术实现有多难,而是在海量并发下如何通过业务规则降噪和容错机制兜底,实现极致的‘流量削峰’与状态同步。它体现了在海量社交系统中,对体验、成本和安全的三角平衡思维。在架构设计上,我们可以总结为四层防御神盾:

  1. 第一层神盾:端侧策略降噪(源头削峰) 微信通过‘收到消息后10秒内输入才触发’以及‘只有接收方保持在当前聊天视窗才触达’的产品规则,结合客户端状态机防抖,确保在 10 秒黄金周期内发送端无论敲击多少次键盘,只会向服务端发送一次 State=1(正在输入)的轻量级信令,在客户端直接拦截了 超90% 的无效高频网络请求。

  2. 第二层神盾:信令网关转发(按需转发) 为了省电省流,并没有采用维持高频数据通道的复用,而是采用轻量级、短断续续的信令握手。消息网关(Gateway)接收到信令后,不盲目透传。而是去高性能缓存(如 Redis/Local Cache)快速查询接收方状态:是否在线?当前活跃视窗是否为发送方?若不匹配,直接丢弃(Drop Logic)该信令,将无谓的转发带宽降至极低。

  3. 第三层神盾:去中心化自毁兜底(容错体验) 接收端在收到信令后显示‘正在输入...’,同时启动一个 5秒本地自毁计时器。计时器超时或收到新消息时,会自动将该状态平滑覆盖和隐藏。这种下推单向信令配合本地定时自毁的设计,完美避开了发送方断网、切后台导致服务器无感知而导致的状态卡死,无需复杂的服务器心跳监测。

  4. 第四层神盾:多维隐私限制(深度过滤) 此外,架构设计必须通过产品策略前置过滤特定场景:表情包发送不触发、PC端微信不触达(因打字习惯不同)、第三方输入法缓冲池盲区(字未进聊天框前不捕捉keystroke)。将用户体验限定在最核心的移动社交场景中。

总结来说,核心思想就是:用产品策略前置削峰,用缓存网关挡并发,用本地超时做容错,在极低的服务端成本下,实现了降本增效与高可用体验的完美闭环。

图片

很多人问过:既然都能做“正在输入”了,微信为什么不做“已读”功能?

因为“已读”意味着“看见了但没回”,这会给社交带来极大的猜忌、焦虑和压迫感。没有已读,是把“回应与否”的选择权,体面地交还给用户。 而“正在输入”,则是一种“有限度的透明”。它保留了对话的气口,就像对方没有马上说话,而是深吸了一口气,张了张嘴。它在告诉你:“我在线,我在乎,我正在回应。”

顶级的系统架构,永远不是生硬地堆砌中间件。它是技术的妥协,也是产品的艺术;它不瞎浪费一丝服务器资源,最后,只用最精简的代码,去成全了人性的温度。

这,才是大厂面试官真正想听到的答案。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐