海外销售反馈:客户端在发送消息时,有时显示感叹号,提示失败,但网络是正常的。
- 在
WIFI
、移动网络情况下 IM
发送消息失败,显示感叹号IM
系统部署在国内,销售在海外
生产环境实际情况:
-
协议:
MQTT
+Protobuf
,在MQTT
协议中可变头部中加入自定义字段协议部分,没有优化空间了。
MQTT
固定头部 2字节,可变头部 2字节。 -
服务器部署在国内(北京机房)
-
网络链路加速:北京
海外环境拦路虎:
- 运营商劫持严重,
DNS
劫持、HTTP
劫持 - 移动网络服务,网路基础建设参差
- 国际网络到国内服务器的延迟高(丢包率高)
优化思路
参考方案:移动弱网络优化方法
优化主要分为:应用层 和 传输层。
IM
通信是 TCP
全双工通行,重点在于 传输层。
- 应用层:协议采用
MQTT
+Protobuf
已经没有什么优化空间了。
-
DNS
的解析改为HTTPDNS
提供
LBS
服务:提供IM
连接的IP
和端口。- 解决域名劫持问题 (东南亚地区回传的数据显示有不少劫持)
- 解决
LocalDNS
非就近分配问题 - 结合业务可以做解析预热。
DNS
的改进上线后观察初始连接请求提升17%的效率。
- 边缘节点动态加速,非常有效
尽可能离用户最近,利用边缘节点对路由、链路进行优化,提高动态服务的效率。
相较于直连模式,使用动态加速后,
P90
的接口延迟效率提升了60%。
实际落地
重点在应用层交互方面。
当前重点问题是客户端与服务器之间的网络连接不稳定:
- 用户提示不友好:用户不知道连接断开了
- 用户交互不友好:弱网、无网下拉取历史消息(消息丢失)
- 消息发送不成功:消息发送失败
解决方案:
- 连接状态显示:网络连接提示
- 优化弱网/无网下消息交互:融合云
- 完善协议重发和超时
- 减少不必要请求:核心数据异步加载、非核心数据访问加载
(1)连接状态显示
客户端分为:移动端(iOS、Android)和 PC。
移动端连接状态可分为:
-
未连接:只有在没有网络情况下,才会显示未连接。
未连接状态时,在消息页面上方提示【网络连接发生问题,请检查您的网络设置】
- 连接中:在有网络的情况下,客户端要么是连接成功,要么就是在连接中。
- 收取中:从连接成功到核心数据收取完成过程。
PC
连接状态分为:
- 当与服务端
socket
断开:在消息页面上方提示【网络连接发生问题,请检查您的网络设置】
(2)融合云:历史消息
场景分析:拉取历史消息
- 有网:都走线上请求没问题
- 无网:走本地消息,或者提示服务不可用
为了减少不必要的请求:增加本地消息,本地已有数据,就不向线上拉取数据。
但存在一个问题:本地消息和线上消息融合问题。
- 什么时候去请求服务器拉取消息?
- 什么时候走本地消息?
举个栗子:
消息
Id
递增
- 本地消息已存储:
[20, 40]
- 上线拉取最新消息:
[200, 220]
这里有个概念:可信区间与不可信区间
-
可信区间:说明消息已经落库,可以直接走本地消息
-
不可信区间:不确定这块是否有消息,需要再请求一次服务
这时候就需要用到 区间合并:
-
本地消息:
[20, 40]
区间是可信区间 -
向上拉取历史消息:
[40, 60]
区间 -
有交集,这时候进行消息融合形成可信区间:
[20, 60]
(3)协议重发和超时
采用 Qos =1
。
服务端重发机制:
- 每次发送后超时时间为 15s,最多发送 6 次。
- 超过次数则放弃
客户端重发机制:
- 每次发送后超时时间为 15s,超时后重发,最多重发 4次。
- 超过次数提示失败或系统繁忙
采用 RetryCommandExecutor
和 RetryMessageExecutor
双延迟队列去实现命令和消息的重试。