IM 中 弱网优化小概述

1,951 阅读4分钟

海外销售反馈:客户端在发送消息时,有时显示感叹号,提示失败,但网络是正常的。

  • WIFI、移动网络情况下
  • IM 发送消息失败,显示感叹号
  • IM 系统部署在国内,销售在海外

生产环境实际情况:

  1. 协议:MQTT + Protobuf,在 MQTT 协议中可变头部中加入自定义字段

    协议部分,没有优化空间了。

    MQTT 固定头部 2字节,可变头部 2字节。

  2. 服务器部署在国内(北京机房)

  3. 网络链路加速:北京

海外环境拦路虎:

  1. 运营商劫持严重,DNS 劫持、HTTP 劫持
  2. 移动网络服务,网路基础建设参差
  3. 国际网络到国内服务器的延迟高(丢包率高)

优化思路

参考:爱奇艺海外App的网络优化实践

参考方案:移动弱网络优化方法

优化主要分为:应用层 和 传输层。

2022-07-0220-06-26.png

IM 通信是 TCP 全双工通行,重点在于 传输层

  • 应用层:协议采用 MQTT + Protobuf 已经没有什么优化空间了。
  1. DNS 的解析改为 HTTPDNS

    提供 LBS 服务:提供 IM 连接的 IP 和端口。

    • 解决域名劫持问题 (东南亚地区回传的数据显示有不少劫持)
    • 解决 LocalDNS 非就近分配问题
    • 结合业务可以做解析预热。

DNS 的改进上线后观察初始连接请求提升17%的效率。

  1. 边缘节点动态加速非常有效

尽可能离用户最近,利用边缘节点对路由、链路进行优化,提高动态服务的效率。

相较于直连模式,使用动态加速后,P90 的接口延迟效率提升了60%。


实际落地

重点在应用层交互方面。

当前重点问题是客户端与服务器之间的网络连接不稳定:

  • 用户提示不友好:用户不知道连接断开了
  • 用户交互不友好:弱网、无网下拉取历史消息(消息丢失)
  • 消息发送不成功:消息发送失败

解决方案:

  1. 连接状态显示:网络连接提示
  2. 优化弱网/无网下消息交互:融合云
  3. 完善协议重发和超时
  4. 减少不必要请求:核心数据异步加载、非核心数据访问加载

(1)连接状态显示

客户端分为:移动端(iOS、Android)和 PC。

移动端连接状态可分为:

  • 未连接:只有在没有网络情况下,才会显示未连接。

    未连接状态时,在消息页面上方提示【网络连接发生问题,请检查您的网络设置】

2022-07-0209-08-35.png

  • 连接中:在有网络的情况下,客户端要么是连接成功,要么就是在连接中。
  • 收取中:从连接成功到核心数据收取完成过程。

PC 连接状态分为:

  • 当与服务端 socket 断开:在消息页面上方提示【网络连接发生问题,请检查您的网络设置】

(2)融合云:历史消息

场景分析:拉取历史消息

  • 有网:都走线上请求没问题
  • 无网:走本地消息,或者提示服务不可用

为了减少不必要的请求:增加本地消息,本地已有数据,就不向线上拉取数据。

但存在一个问题:本地消息和线上消息融合问题。

  • 什么时候去请求服务器拉取消息?
  • 什么时候走本地消息?

举个栗子:

消息Id 递增

  • 本地消息已存储:[20, 40]
  • 上线拉取最新消息:[200, 220]

2022-07-0308-27-37.png

这里有个概念:可信区间与不可信区间

  • 可信区间:说明消息已经落库,可以直接走本地消息

  • 不可信区间:不确定这块是否有消息,需要再请求一次服务

这时候就需要用到 区间合并

  • 本地消息:[20, 40] 区间是可信区间

  • 向上拉取历史消息:[40, 60]区间

  • 有交集,这时候进行消息融合形成可信区间:[20, 60]

(3)协议重发和超时

采用 Qos =1

服务端重发机制:

  • 每次发送后超时时间为 15s,最多发送 6 次。
  • 超过次数则放弃

客户端重发机制:

  • 每次发送后超时时间为 15s,超时后重发,最多重发 4次。
  • 超过次数提示失败或系统繁忙

采用 RetryCommandExecutorRetryMessageExecutor 双延迟队列去实现命令和消息的重试。