我在业余时间开发了一款自己的独立产品:升讯威在线客服与营销系统。陆陆续续开发了几年,从一开始的偶有用户尝试,到如今线上环境和私有化部署均有了越来越多的稳定用户,在这个过程中,我也在不断的提高着自己的技术广度和深度。
在过去的几个月,我对升讯威客服系统的底层网络实现进行了持续的重构和完善,实现了更健壮的网络传输层。新版本从4月初给一个外贸客户上线后,24/7运行至今,确认了稳定性和可靠性。可能有朋友要问了:不就是 WebSocket 收发消息吗?扯什么"网络传输层"? 笑,这就是我这一系列博客要系统阐述的问题了。
前言
在近几年接触的用户中,有许多从事跨境电商业务,特别是针对欧美市场的产品销售。通常这些用户会选择建立产品销售独立站,然后在网站上添加在线客服系统,实现对引流而来的访客实时监控,主动打招呼施展话术,提高转化率。
大部分跨境电商企业都会选择将服务器部署在香港,兼顾国内客服登录和欧美访客访问。这是一个非常复杂的网络结构,访问路径跨越多个运营商与国际链路,国内客服在登录香港服务器时,中间涉及多次网络跳转,欧美访客在访问时,特别是欧洲访客,同样也面临多次网络跳转。同时,部署客服系统的用户为了网络安全,会选择使用防火墙,CDN、DCDN 加速等技术。而访客那一侧,很多时候用的还是手机 APP,会面临网络切换,高频的网络抖动问题。
在这种非常复杂的网络结构中,如果只是发布无状态的 HTTP 服务,例如网站或各种管理系统,其实并没有什么难度,甚至开发者根本不需要关心网络层面的问题。但对客服系统来说,要保持可靠的长连接,这就有点地狱难度了。
很多人第一次接触在线客服系统时,都会下意识地认为: "这不就是一个聊天窗口吗?"前端建立一个 WebSocket 连接,服务端转发消息,再配一个管理后台,不就行了吗?有什么难的?
有一次我在一个技术群提到在线客服系统的实现有一些难度时,被一个年轻小伙喷了,他就是这么想的,告诉我使用 WebSocket 就行了,让我别扯淡 😅。
在本地开发环境中,这种想法甚至很容易得到"验证":两台开发测试用电脑、一个稳定网络、最新的 Chrome 浏览器、没有运营商干扰、没有复杂代理、没有跨境链路、没有移动网络切换。一切都运行得很好,于是很多人会产生一种错觉:确实不复杂。于是一通猛干(自行研发)上线之后,崩了:
- WebSocket 被中间代理莫名断开
- CDN 或反向代理清理长时间空闲连接
- 企业网络禁止 Upgrade 请求
- 移动网络切换导致连接失效
- 浏览器后台节能机制导致心跳暂停
- 某些地区 TLS 握手异常缓慢
- NAT 映射提前回收
- 国际链路抖动导致消息延迟飙升
- 某些网络环境下连接成功率极低
于是你想打个日志,甚至远程打个断点调试一下,但是随之你会发现这些问题偶发度极高,没有规律,即便你通过日志捕获到某个数据异常,但无论怎么 Review 代码,你都找不到它为空的理由,看起来代码根本不可能走到那个位置,但问题就是会时不时来一下。再叠加 async/await 全异步编程模型,于是开发者会陷入一种非常非常痛苦的状态(我曾经的状态),用户不断反馈"偶发异常",但开发环境里永远一切正常,甚至其它用户都正常,就他那儿有这种"偶发异常",不同的客户有不同的"偶发异常" 😅。这也是很多实时系统真正困难的地方。
在线客服系统最难的部分,从来不是"消息发送成功"。而是:在真实、复杂、不可控、充满噪声的全球网络环境中,系统是否仍然能够长期、稳定、可靠地运行。而这恰恰也是大量实时通信产品最容易被低估的部分。
在这个系列中,我会结合构建升讯威客服系统过程中的实际经验,持续讨论:
- 跨国网络环境下的实时通信问题
- WebSocket 在真实互联网中的各种边界情况
- 浏览器与移动网络环境中的连接稳定性
- 长连接保活与异常恢复
- 消息可靠投递
- API 健康检测
- 多区域部署
- SaaS 与私有化部署架构
- 高延迟与弱网环境优化
- 实时系统中的各种工程取舍
本篇:网络路径的不可控性
很多人对互联网存在一种天然误解:"既然都是联网,数据应该会自动选择一条最快的路。" 但现实并不是这样。尤其是在跨国网络环境中,数据传输路径往往混乱、复杂,甚至带有很强的随机性。对于在线客服系统这类实时通信场景而言,这种"不确定性"会被进一步放大。因为实时系统最怕的并不是"慢"。而是"不稳定",例如:
- 延迟突然抖动
- 短时间丢包
- RTT 剧烈波动
- 路由临时切换
- 链路间歇性拥塞
- TCP 长连接状态异常
这些问题在无状态系统,例如普通网页浏览,或各种管理后台中,很多时候并不明显。因为网页加载属于"短连接 + 容错型"场景。 慢一点用户只是觉得页面加载有点慢,不行刷新几次就正常了。但在线客服系统不同,它依赖的是长时间保持的实时连接,在此基础之上实现双向消息传输、状态同步。如果一款在线客服系统没有非常健壮的网络层,那么一旦网络路径出现波动,丢消息,掉线就会经常发生。
"跨国网络"下的链路复杂度
当数据传输发生在同一城市、同一运营商网络内时,路径通常相对稳定。但一旦跨国,情况会迅速复杂化。例如一个美国用户访问部署在亚洲的在线客服系统。看起来只是:"用户访问服务器"。但实际上,中间可能经过:
- 本地 ISP
- 区域骨干网
- 国际出口
- 海底光缆
- 中转节点
- 跨运营商互联
- CDN 或反向代理节点
- 目标区域网络
其中任何一个环节出现波动,都可能影响最终连接质量。并且这些路径通常并不是固定的。互联网路由本身就是动态变化的,今天走东京明天绕新加坡。某些情况下,看似"美国 ⇄ 亚洲"的通信,实际会绕行多个国家和地区。
要在这种复杂网络链路下, 24/7 维持稳定的长连接是非常复杂的工作。CRUD Boys 在代码中 new 一个 WebSocket 收发消息,离真正"能用"的客服系统还相差一个银河系。
延迟并不是最大的问题
很多人会把跨国网络问题简单理解为:"只是有点慢, Ping 高一点。" 实际上高延迟本身并不可怕,实时通信系统怕的是"不稳定",例如:
- RTT 从 80ms 突然跳到 900ms
- 某几个数据包随机丢失
- 某条链路瞬时拥塞
- TCP 重传突然增多
- 网络出现短时间 freeze
这些情况在普通网页浏览,使用管理后台类系统时,很可能完全无感,但对在线客服系统来说,每个问题都是坑,因为实时系统依赖持续的数据流动,一旦链路发生抖动:
- 心跳可能超时
- WebSocket 可能断开
- 消息顺序可能异常
- 用户在线状态可能错误
- 输入状态同步可能卡顿
- 客服端会误判访客离线
于是用户看到的现象就会变成:"系统有时候很好,有时候突然抽风。"而这种问题很难排查定位,偶发且无法复现。
海底光缆可靠吗
大部分国际通信依赖海底光缆。而海底光缆并不是一个"永远稳定"的系统。现实中会发生:
- 光缆故障
- 维护切换
- 区域拥塞
- 自然灾害影响
- 国际出口异常
- 路由临时调整
某些时候用户甚至不会完全断网。只是:
- 延迟突然变高
- 某些区域访问异常缓慢
- WebSocket 频繁断开
- TLS 握手明显变慢
对于普通网页来说,这可能只是偶尔"打开慢一点"。但对于在线客服系统这种持续长连接场景,影响会被成倍放大,一个不可靠的在线客服系统就会出现丢消息,串消息的问题。
实时系统比普通 Web 系统更"脆弱"
对于无状态系统来说,比如传统 Web 系统是"请求-响应"模式。请求失败了可以刷新,超时了可以重试。但实时系统不同,它需要 "持续活着的一条连接",系统需要长时间维持:
- TCP 状态
- WebSocket 状态
- 心跳状态
- 在线状态
- 消息同步状态
在此基础之上客服系统要保证:不丢消息,不串消息,访客状态正常,客服 24/7 在线。再叠一层:生产级客服系统有时面临数百、数千访客在线,节假日大促瞬时流量洪峰......
而跨国网络环境最大的特点,就是它会不断破坏这种"持续稳定",给你一个"薛定谔的网络"。所以很多在线客服系统在本地测试时表现良好,一旦真正投入生产环境,投入全球网络环境,就会开始出现各种"偶发问题",就会让你感觉到不靠谱。这些问题的根源,往往是开发者一开始就低估了真实互联网本身的复杂度。
如果您感兴趣:
升讯威客服系统仍处于不断演进的过程中。
如果您曾经构建或部署过实时聊天系统,我非常期待与您交流心得。
- 🌐 官方网站:https://kf.shengxunwei.com
- 📘 技术文档:https://docs.shengxunwei.com
无论您倾向于使用托管版还是自行部署(Self-hosting),都可以免费试用。
希望能够打造: 开放、开源、共享。努力打造一款优秀的社区开源产品。
钟意的话请给个赞支持一下吧,谢谢~