阿里IM技术分享:闲鱼亿级IM消息系统的及时性优化实践
Posted im中国人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阿里IM技术分享:闲鱼亿级IM消息系统的及时性优化实践相关的知识,希望对你有一定的参考价值。
本文由阿里闲鱼技术团队有攸分享,原题“向消息延迟说bybye:闲鱼消息及时到达方案”,有修订和改动,感谢作者的分享。
1、引言
IM消息作为闲鱼用户重要的交易咨询工具,核心目标有两点:
- 1)第一是保证用户的消息不丢失;
- 2)第二是保证用户的消息及时送达接收方。
IM消息根据消息的接收方设备是否在线,分为离线和在线推送。数据显示目前闲鱼每天有超过一半以上的IM消息是走在线通道的,而在线消息的到达率、及时性是直接影响用户体验的。
本文将根据闲鱼IM消息系统在消息及时性方面的优化实践,详细分析了IM在线通道面临的各种技术问题,并通过相应的技术手段来优化从而保证用户消息的及时到达。
PS:如果您对IM消息可靠性还没有概念,建议先阅读这篇入门文章《零基础IM开发入门(二):什么是IM系统的实时性?》。
学习交流:
- 即时通讯/推送技术开发交流5群:215477170 [推荐]
- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》
- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK
(本文同步发布于:http://www.52im.net/thread-3726-1-1.html)
2、系列文章
本文是系列文章的第5篇,总目录如下:
- 《阿里IM技术分享(一):企业级IM王者——钉钉在后端架构上的过人之处》
- 《阿里IM技术分享(二):闲鱼IM基于Flutter的移动端跨端改造实践》
- 《阿里IM技术分享(三):闲鱼亿级IM消息系统的架构演进之路》
- 《阿里IM技术分享(四):闲鱼亿级IM消息系统的可靠投递优化实践》
- 《阿里IM技术分享(五):闲鱼亿级IM消息系统的及时性优化实践》(* 本文)
3、当前面临的问题
3.1 端内长连接中断
在IM场景中,用户与云端通信频繁,且为了实现用户的消息及时到达,往往采用云端下推消息的方式触达用户,所以用户在线时设备与云端会维持一条TCP长连接通道,可以更轻量级的与服务端进行交互,现代IM即时通讯的下行消息都是通过长连下发的。
当前闲鱼IM消息系统使用的是ACCS长连接,ACCS是淘宝无线提供的全双工、低延时、高安全的通道服务。
但由于用户设备网络状态的不确定性,可能会发生各种各样的网络异常情况导致ACCS长连接通道中断。而长连接一旦意外中断,就会导致用户无法及时收到在线消息。
针对这个问题,我们需要尽可能及时的感知到长连中断并尝试重连。具体的优化思路会在本文后面的内容中分享。
3.2 下推的消息未达
感知长连中断并重连只能在大多数时间保证长连接的有效性,但是在长连接无效或不稳定期间下推的消息客户端可能根本收不到。
简单说就是仅仅有重连机制无法保证下行消息必达,可能有以下场景导致下行消息失败:
- 1)服务端发送下行消息时长连畅通,消息在传输路上通道断掉,客户端无法收到;
- 2)设备的在线状态存在延迟,服务端下行消息时认为设备在线,实际上设备已经离线,无法收到;
- 3)客户端收到了下行消息,但端上后续处理失败(比如落库失败,消息没有成功展示给用户)。
我们通过数据埋点统计得出,ACCS长连接的下行成功率在97%左右。
ACCS长连接的下行成功率的统计方法如下:
ACCS下行成功率 = 通过ACCS成功下行且客户端收到的消息量 / 服务端认为通过ACCS成功下行的消息量
有心急的同学就要问了,丢了3%的消息吗?
并没有!这3%的消息不会丢失,只是不保证及时触达给用户。
我们的消息同步模型是推拉结合模式,在用户拉取消息时会拉取到设备当前位点与服务端最新位点的所有消息,ACCS下行失败的消息会通过主动拉模式获取到,但客户端主动拉取消息的触发时机有限。
当前客户端主动拉取消息的触发时机主要有以下几个:
- 1)用户冷启动app,主动同步消息;
- 2)用户主动下拉刷新;
- 3)app后台切换前台;
- 4)收到一条推送消息,客户端发现新消息的位点跟本地最新的位点有gap,触发同步。
可见:上述主动同步消息的触发很大程度上依赖用户行为或者有没有收到新消息,难以保证消息及时到达。
如果是用户高频打开的IM软件,这样也不会有太大的问题。但是闲鱼app的活跃度较低,有时候甚至依赖IM消息拉活,而且一条延迟的消息触达可能导致用户错过一笔交易,闲鱼消息不允许有这样的延迟发生。
基于上述分析,我们先描述一个数据指标来反映现状。
通过上面的描述可知:ACCS消息并不全都是推下来的,也可能是主动拉下来的。如果是推,必定可以及时到达;如果是拉,则受限于用户行为。
拉的这部分消息,我们定义为ACCS消息补偿到达,然后计算ACCS消息补偿到达耗时,消息范围限定为服务端ACCS成功下行但是客户端通过主动拉取同步到的消息,以往的版本这个数据在60分钟左右。
注意:这个数据并不是消息触达到用户的耗时,因为如果在线转离线触达,拉取到消息的时间取决于用户行为(用户何时打开了app),但这个数据也能大致反映在线消息的到达延迟状况。
ACCS长连接的消息补偿到达耗时的统计方法如下:
ACCS消息补偿到达耗时 = 客户端通过拉获取到ACCS消息的时间 - 服务端ACCS下行时间
接下来本文将从长连接的重连和未达消息重发两个方面详细讲述我们是如何优化在线通道稳定性的,从而优化并保证消息的及时到达。
4、优化手段1:增加长连接重连机制
4.1 长连接为什么会中断?
有因必有果,我们先来分析下有哪些原因会导致连接中断。
对于IM这种场景下来说,通常可能有以下原因:
- 1)用户设备断网;
- 2)设备发生了网络切换;
- 3)设备处于弱网环境,网络不稳定;
- 4)设备网络正常,TCP连接由于NAT超时导致连接被运营商中断。
对于APP来说,如果是用户操作导致网络状态变化的情况,会有网络状态变化事件通知,这种情况可以监听事件并主动尝试重连。但现实中的大多数情况都是“意料之外”(正如上面列举的这些断网可能性一样)。
那么既然“意料之外”的断网无法预知,技术上可以如何有效的感知到各种异常状况呢?
PS:如果要透彻理解断网、弱网、TCP链接有效性,并不是本文能讲的清楚的,可以参照下面的资料深入理解一下,值得好好学习。
关于TCP链接本身的有效性问题,可以读以下两篇:
关于移动网络的复杂性问题,可以从以下几篇入门的科普文章学习一下:
- 《IM开发者的零基础通信技术入门(十一):为什么WiFi信号差?一文即懂!》
- 《IM开发者的零基础通信技术入门(十二):上网卡顿?网络掉线?一文即懂!》
- 《IM开发者的零基础通信技术入门(十三):为什么手机信号差?一文即懂!》
- 《IM开发者的零基础通信技术入门(十四):高铁上无线上网有多难?一文即懂!》
关于移动弱网带来的各种问题、优化方案等,可以通过以下几篇系统学习一下:
- 《现代移动端网络短连接的优化手段总结:请求速度、弱网适应、安全保障》
- 《移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”》
- 《移动端IM开发者必读(二):史上最全移动弱网络优化方法总结》
- 《百度APP移动端网络深度优化实践分享(三):移动端弱网优化篇》
4.2 心跳检测机制
像大多数链路保活场景一样,IM这种场景下最有效的检测手段就是心跳检测(如果你对TCP链路保活还没有什么概念,建议先读《为何基于TCP协议的移动端IM仍然需要心跳保活机制?》)。
原理就是:客户端通过定时发送心跳包,服务端收到心跳包后再反馈给客户端,通过客户端和服务端这一来一去的配合,就可以实现客户服和服务端各自都能感知到连接是否中断。
从及时性效果来看:心跳间隔越短越好,而频繁的心跳检测势必会带来用户流量以及电量的损耗,所以我们的实现目标是如何尽可能少的心跳检测而又尽量及时地感知到长连中断的意外情况。
状态机+消息心跳队列:
在心跳协议设计上,要注意心跳包的核心目标是检测长连通道是否畅通,客户端主动上行心跳包且能收到服务端回包,就认为长连通道健康。所以心跳的上行消息以及回包的数据包应尽可能小。一般来说,通过协议头标识心跳包及响应即可(这样就能节省协议包大小)。
PS:关于心跳机制的入门文章可以详读《一文读懂即时通讯应用中的网络心跳包机制:作用、原理、实现思路等》。
4.3 心跳策略
心跳策略是实现我们上述目标的核心机制,本文仅简单列举几种心跳策略。
比如以下这几种:
- 1)短心跳检测 初始状态连续 ping 3次 收到 ACK 后,可以认为进入稳定状态;
- 2)常规固定时长心跳(根据app状态不同,频率可调Mid+,Mid-, Long);
- 3)自适应心跳 根据设备网络状态变化自动适应的心跳间隔;
- 4)冗余心跳,app后台切前台,主动心跳一次。
关于心跳策略的详细设计甚至可以单独写一篇文章,有兴趣的同学可以阅读以下推荐的文章继续深入研究。
- 《微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)》
- 《移动端IM实践:实现Android版微信的智能心跳机制》
- 《移动端IM实践:WhatsApp、Line、微信的心跳策略分析》
- 《融云技术分享:融云安卓端IM产品的网络链路保活技术实践》
- 《Web端即时通讯实践干货:如何让你的WebSocket断网重连更快速?》
- 《正确理解IM长连接的心跳及重连机制,并动手实现(有完整IM源码)》
- 《一种Android端IM智能心跳算法的设计与实现探讨(含样例代码)》
- 《手把手教你用Netty实现网络通信程序的心跳机制、断线重连机制》
5、优化手段2:消息ACK应答与重发机制
5.1 概述
为了解决上面的问题,我们同时也引入了消息ACK应答与重发机制。
整体思路是:客户端在收到ACCS消息并处理成功后,给服务端回一个ACK应答包,服务端下发ACCS消息时将消息加入重试队列,收到ACK应答包后更新消息到达状态,并终止重试。
整体设计流程图如下:
该方案的难点即重试处理器的实现设计,接下来我们将重点讲述这部分的详细设计。
5.2 重试队列存储设计
我们采用阿里云表格存储TimeLine模型来存储下行消息的到达状态。Timeline 模型是针对消息数据场景所设计的数据模型,它能满足消息数据场景对消息保序、海量消息存储、实时同步的特殊需求,在IM、Feed流等消息场景应用广泛。(关于TimeLine模型,这里有篇详细的文章可以学习一下《现代IM系统中聊天消息的同步和存储方案探讨》)
我们给每个用户设备定义一个TimeLine,timeline-id定义为userId_deviceId,sequenceId自定义为消息位点。
存储结构如下:
每通过ACCS成功下行一条消息,则插入到接收用户设备的TimeLine中,收到ACK后根据消息id更新消息到达状态。
同时由于重试动作只发生在下行消息后较短的一段时间内,所以我们设置一个比较短的全局过期时间即可,避免数据膨胀。
5.3 延迟重试设计
如上图所示:
- 1)每通过ACCS下发一条消息,先插入到Timeline中,初始状态为未达,然后生产一条延迟N秒的延迟消息;
- 2)每次消费到延迟消息后,读取tablestore中该消息的到达状态,如到达则终止延迟,否则继续;
- 3)每次重试先判断设备是否在线,如果设备不在线,转发离线通道并终止重试,如果设备在线,则重推未到达的消息,并再次延迟N秒消费;
- 4)每条消息的重试生命周期中用的同一条延迟消息,最多重试消费M次,超过次数不再重试并打日志埋点(后续可以监控这种情况并基于这个数据进行优化)。
5.4 延迟重发策略
延迟重发策略是指在重发流程中,如何选择合适的延迟时间来使得重发的效率最高。
不同用户在不同时间、地点所处的网络环境差别较大,网络恢复到稳定态所需要的时间也有差异,需要选用合适的延迟策略来保证重发效率。
最优的延迟策略的目标是在最短的时间内,使用最少的重发次数将消息投递成功。以下是几种可选的方案。
5.4.1)固定延迟时间:
要想找到最优的延迟策略,必须从数据中通过分析得到答案,天马行空的想象往往离实际相差甚远。
我们先采用固定的延迟时间(10s)最大重试6次来分析一波数据:
通过这组数据可以看到:有约85%的消息在40s内重发可以投递成功,还有12%的消息在达到最大重试次数后依旧没有收到ACK。在4次重试之后,第5次成功只有2.03%,第6次只有0.92%,继续重发的收益已经变得很低。
6次以后还有部分消息没有收到ACK,这部分消息如果用固定延迟时间策略,性价比很低,频繁重发浪费系统资源,我们需要继续改进策略。
5.4.2)固定延迟+固定步长递增:
考虑到部分用户的网络短时间无法恢复,频繁的短间隔重发价值不大,我们采用4次固定短间隔延迟N秒后,每次延迟时间都是上一次延迟时间递增固定步长M秒的策略。直到收到ACK、用户设备离线或者达到了最大延迟时间MAX(N)。
这种策略一定程度上可以解决固定延迟时间重发策略的问题,但如果用户短时间网络无法恢复,每次重发都要重新递增,也不是一种最优解。
5.4.3)自适应延迟:
设计流程图:
如上图:我们最终衍生出了自适应延迟策略。
自适应延迟是指:根据用户的网络状况,采取自动调整的延迟时间,以期望达到最高的重发效率。
具体是:新消息先通过4次固定N秒的短延迟来探测设备的网络状况,一旦网络恢复,我们将设备的N值清空(设备N值是指根据上几次重发经验,当前设备网络能回复ACK所需要的最短时间,默认情况该值为空,代表用户设备网络正常)。4次重发后依旧收不到ACK,我们尝试读取设备N值,如果为空,则取初始值,以后每次延迟都递增固定步长M,并在重发后更新当前设备的N值,直到消息收到ACK或者达到了最大延迟时间MAX(N)。
5.5 新老版本兼容性
需要注意的是老版本的app是不会回ACK的,如果下发给老版本设备的消息也加入重试队列,那此类消息将一直重试到最大次数才会终止,无端消耗资源。
所以我们设计在ACCS长连建立之后,客户端主动上行一条设备信息,其中包含app的版本号,服务端存储一定时间,在将消息加入重试队列之前,先校验接收者设备app的版本号,符合要求再加入重试队列。
6、 最终优化后的效果
消息重连重发方案上线后,我们上面定义的指标 ACCS补偿到达时间 从60分钟大幅降低至15分钟,降幅达75%。
从而印证了我们的技术分析,同时用户有关消息延迟的舆情反馈大幅下降,可见消息重发机制对保证用户消息及时到达成效显著。
7、未来展望
消息在线通道的稳定性优化至此已告一段落,未来我们将继续优化闲鱼消息的使用体验,包括基础功能的完善以及基础体验的提升。
基础功能方面:我们在近期的版本中已经支持了消息撤回、草稿功能,后续将逐步支持发送定位,会话分组、备注,消息搜索等功能。
基础体验方面:我们对消息的UI样式做了优化升级,并优化了app消息tab页的cpu及内存使用,后续将继续从流量、电量、性能方面继续优化消息的使用体验。
附录:参考资料
[1] 为何基于TCP协议的移动端IM仍然需要心跳保活机制?
[2] 不为人知的网络编程(十二):彻底搞懂TCP协议层的KeepAlive保活机制
[4] 现代移动端网络短连接的优化手段总结:请求速度、弱网适应、安全保障
[5] 移动端IM开发者必读(二):史上最全移动弱网络优化方法总结
[6] IM开发者的零基础通信技术入门(十二):上网卡顿?网络掉线?一文即懂!
[7] IM开发者的零基础通信技术入门(十三):为什么手机信号差?一文即懂!
[8] 移动端IM实践:实现Android版微信的智能心跳机制
[9] 融云技术分享:融云安卓端IM产品的网络链路保活技术实践
[10] Web端即时通讯实践干货:如何让你的WebSocket断网重连更快速?
本文已同步发布于“即时通讯技术圈”公众号。
作者:Jack Jiang (点击作者姓名进入Github)
出处:http://www.52im.net/space-uid-1.html
交流:欢迎加入即时通讯开发交流群 215477170
讨论:http://www.52im.net/
Jack Jiang同时是【原创Java
Swing外观工程BeautyEye】和【轻量级开源移动端即时通讯框架MobileIMSDK】的作者,可前往下载交流。
本博文
欢迎转载,转载请注明出处(也可前往 我的52im.net 找到我)。
阿里IM技术分享:闲鱼亿级IM消息系统的离线推送到达率优化
本文由阿里闲鱼技术团队逸昂分享,原题“消息链路优化之弱感知链路优化”,有修订和改动,感谢作者的分享。
1、引言
闲鱼的IM消息系统作为买家与卖家的沟通工具,增进理解、促进信任,对闲鱼的商品成交有重要的价值,是提升用户体验最关键的环节。
然而,随着业务体量的快速增长,当前这套消息系统正面临着诸多急待解决的问题。
以下几个问题典型最为典型:
- 1)在线消息的体验提升;
- 2)离线推送的到达率;
- 3)消息玩法与消息底层系统的耦合过强。
经过评估,我们认为现阶段离线推送的到达率问题最为关键,对用户体验影响较大。
本文将要分享的是闲鱼IM消息在解决离线推送的到达率方面的技术实践,内容包括问题分析和技术优化思路等,希望能带给你启发。
学习交流:
- 即时通讯/推送技术开发交流5群:215477170 [推荐]
- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》
- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK
(本文已同步发布于:http://www.52im.net/thread-3748-1-1.html )
2、系列文章
本文是系列文章的第6篇,总目录如下:
- 《阿里IM技术分享(一):企业级IM王者——钉钉在后端架构上的过人之处》
- 《阿里IM技术分享(二):闲鱼IM基于Flutter的移动端跨端改造实践》
- 《阿里IM技术分享(三):闲鱼亿级IM消息系统的架构演进之路》
- 《阿里IM技术分享(四):闲鱼亿级IM消息系统的可靠投递优化实践》
- 《阿里IM技术分享(五):闲鱼亿级IM消息系统的及时性优化实践》
- 《阿里IM技术分享(六):闲鱼亿级IM消息系统的离线推送到达率优化》(* 本文)
3、通信链路类型的划分
从数据通信链接的技术角度,我们根据闲鱼客户端是否在线,将整体消息链路大致分为强感知链路和弱感知链路。
强感知链路由以下子系统或模块:
- 1)发送方客户端;
- 2)idleapi-message(闲鱼的消息网关);
- 3)heracles(闲鱼的消息底层服务);
- 4)accs(阿里自研的长连接通道);
- 5)接收方客户端组成。
整条链路的核心指标在于端到端延迟和消息到达率。
强感知链路中的双方都是在线的,消息到达客户端就可以保证接收方感知到。强感知链路的主要痛点在消息的端到端延迟。
弱感知链路与强感知链路的主要不同在于:弱感知链路的接收方是离线的,需要依赖离线推送这样的方式送达。
因此弱感知链路的用户感知度不强,其核心指标在于消息的到达率,而非延迟。
所以当前阶段,优化弱感知链路的重点也就是提升离线消息的到达率。换句话说,提升离线消息到达率问题,也就是优化弱感知链路本身。
4、消息系统架构概览
下图一张整个IM消息系统的架构图,感受下整体链路:
如上图所示,各主要组件和子系统分工如下:
- 1)HSF是一个远程服务框架,是dubbo的内部版本;
- 2)tair是阿里自研的分布式缓存框架,支持 memcached、Redis、LevelDB 等不同存储引擎;
- 3)agoo是阿里的离线推送中台,负责整合不同厂商的离线推送通道,向集团用户提供一个统一的离线推送服务;
- 4)accs是阿里自研的长连接通道,为客户端、服务端的实时双向交互提供便利;
- 5)lindorm是阿里自研的NoSQL产品,与HBase有异曲同工之妙;
- 6)域环是闲鱼消息优化性能的核心结构,用来存储用户最新的若干条消息。
强感知链路和弱感知链路在通道选择上是不同的:
- 1)强感知链路使用accs这个在线通道;
- 2)弱感知链路使用agoo这个离线通道。
5、弱感知链路到底怎么定义
通俗了说,弱感知链路指的就是离线消息推送系统。
相比较于在线消息和端内推送(也就是上面说的强感知链路),离线推送难以确保被用户感知到。
典型的情况包括:
- 1)未发送到用户设备:即推送未送达用户设备,这种情况可以从通道的返回分析;
- 2)发送到用户设备但没有展示到系统通知栏:闲鱼曾遇到通道返回成功,但是用户未看到推送的案例;
- 3)展示到通知栏,并被系统折叠:不同安卓厂商对推送的折叠策略不同,被折叠后,需用户主动展开才能看到内容,触达效果明显变差;
- 4)展示到通知栏,并被用户忽略:离线推送的点击率相比于在线推送更低。
针对“1)未发送到用户设备”,原因有:
- 1)离线通道的token失效;
- 2)参数错误;
- 3)用户关闭应用通知;
- 4)用户已卸载等。
针对“3)展示到通知栏,并被系统折叠”,原因有:
- 1)通知的点击率;
- 2)应用在厂商处的权重;
- 3)推送的数量等。
针对“4)展示到通知栏,并被用户忽略”,原因有:
- 1)用户不愿意查看推送;
- 2)用户看到了推送,但是对内容不感兴趣;
- 3)用户在忙别的事,无暇处理。
总之:以上这些离线消息推送场景,对于用户来说感知度不高,我们也便称之为弱感知链路。
6、弱感知链路的逻辑构成
我们的弱感知链路分为3部分,即:
- 1)系统;
- 2)通道;
- 3)用户。
共包含了Hermes、agoo、厂商、设备、用户、承接页这几个环节。具体如下图所示。
从推送的产生到用户最终进入APP,共分为如下几个步骤:
- 步骤1:Hermes是闲鱼的用户触达系统,负责人群管理、内容管理、时机把控,是整个弱感知链路的起点。;
- 步骤2:agoo是阿里内部承接离线推送的中台,是闲鱼离线推送能力的基础;
- 步骤3:agoo实现离线推送依靠的是厂商的推送通道(如:苹果的apns通道、Google的fcm通道、及国内各厂商的自建通道。;
- 步骤4:通过厂商的通道,推送最终出现在用户的设备上,这是用户能感知到推送的前提条件;
- 步骤5:如果用户刚巧看到这条推送,推送的内容也很有趣,在用户的主动点击下会唤起APP,打开承接页,进而给用户展示个性化的商品。
经过以上5个步骤,至此弱感知链路就完成了使命。
7、弱感知链路面临的具体问题
弱感知链路的核心问题在于:
- 1)推送的消息是否投递给了用户;
- 2)已投递到的消息用户是否有感知。
这对应推送的两个阶段:
- 1)推送消息是否已到达设备;
- 2)用户是否查看推送并点击。
其中:到达设备这个阶段是最基础的,也是本次优化的核心。
我们可以将每一步的消息处理量依次平铺,展开为一张漏斗图,从而直观的查看链路的瓶颈。
漏斗图斜率最大的地方是优化的重点,差异小的地方不需要优化:
通过分析以上漏斗图,弱感知链路的优化重点在三个方面:
- 1)agoo受理率:是指我们发送推送请到的数量到可以通过agoo(阿里承接离线推送的中台)转发到厂商通道的数量之间的漏斗;
- 2)厂商受理率:是指agoo中台受理的量到厂商返回成功的量之间的漏斗;
- 3)Push点击率:也就通过以上通道最终已送到到用户终端的消息,是否最终转化为用户的主动“点击”。
有了优化方向,我们来看看优化手段吧。
8、我们的技术优化手段
跟随推送的视角,顺着链路看一下我们是如何进行优化的。
8.1 agoo受理率优化
用户的推送,从 Hermes 站点搭乘“班车”,驶向下一站: agoo。
这是推送经历的第一站。到站一看,傻眼了,只有不到一半的推送到站下车了。这是咋回事嘞?
这就要先说说 agoo 了,调用 agoo 有两种方式:
- 1)指定设备和客户端,agoo直接将推送投递到相应的设备;
- 2)指定用户和客户端,agoo根据内部的转换表,找到用户对应的设备,再进行投递。
我们的系统不保存用户的设备信息。因此,是按照用户来调用agoo的。
同时:由于没有用户的设备信息,并不知道用户是 iOS 客户端还是 Android 客户端。工程侧不得不向 iOS 和 Android 都发送一遍推送。虽然保证了到达,但是,一半的调用都是无效的。
为了解这个问题:我们使用了agoo的设备信息。将用户转换设备这一阶段提前到了调用 agoo 之前,先明确用户对应的设备,再指定设备调用 agoo,从而避免无效调用。
agoo调用方式优化后,立刻剔除了无效调用,agoo受理率有了明显提升。
至此:我们总算能对 agoo 受理失败的真正原因做一个高大上的分析了。
根据统计:推送被 agoo 拒绝的主要原因是——用户关闭了通知权限。同时,我们对 agoo 调用数据的进一步分析发现——有部分用户找不到对应的设备。 优化到此,我们猛然发现多了两个问题。
那就继续优化呗:
- 1)通知体验优化,引导打开通知权限;
- 2)与agoo共建设备库,解决设备转换失败的问题。
这两个优化方向又是一片新天地,我们择日再聊。
8.2 厂商推送通道受理率优化
推送到达 agoo ,分机型搭乘厂商“专列”,驶向下一站:用户设备。
这是推送经历的第二站。出站查票,发现竟然超员了。
于是乎:我们每天有大量推送因为超过厂商设定的限额被拦截。
为什么会这样呢?
实际上:提供推送通道的厂商(没错,各手机厂商的自家推送通道良莠不齐),为了保证用户体验,会对每个应用能够推送的消息总量进行限制。
对于厂商而言,这个限制会根据推送的类型和应用的用户规模设定——推送主要分为产品类的推送和营销类的推送。
厂商推送通道对于不同类型消息的限制是:
- 1)对于产品类推送,厂商会保证到达;
- 2)对于营销类推送,厂商会进行额度限制;
- 3)未标记的推送,默认作为营销类推送对待。
我们刚好没有对推送进行标记,因此触发了厂商的推送限制。
这对我们的用户来说,会带来困扰。闲鱼的交易,很依赖买卖家之间的消息互动。这部分消息是需要确保到达的。
同样:订单类的消息、用户的关注,也需要保证推送给用户。
根据主流厂商的接口协议,我们将推送的消息分为以下几类,并进行相应标记:
- 1)即时通讯消息;
- 2)订单状态变化;
- 3)用户关注内容;
- 4)营销消息这几类。
同时,在业务上,我们也进行了推送的治理——将用户关注度不高的消息,取消推送,避免打扰。
经过这些优化,因为超过厂商限额而被拦截的推送实现了清零。
8.3 Push点击率优化
通过优化agoo受理率、厂商受理率,我们解决了推送到达量的瓶颈。但即使消息被最终送达,用户到底点击了没有?这才是消息推送的根本意义所在。
于是,在日常的开发测试过程中,我们发现了推送的两个体验问题:
- 1)用户点击Push有开屏广告;
- 2)营销Push也有权限校验,更换用户登陆后无法点击。
对于开屏广告功能,我们增加了Push点击跳过广告的能力。
针对Push的权限校验功能,闲鱼根据场景做了细分:
- 1)涉及个人隐私的推送,保持权限校验不变;
- 2)营销类的推送,放开权限校验。
以上是点击体验的优化,我们还需要考虑用户的点击意愿。
用户点击量与推送的曝光量、推送素材的有趣程度相关。推送的曝光量又和推送的到达量、推送的到达时机有关。
具体的优化手段是:
- 1)在推送内容上:我们需要优化的是推送的时机和相应的素材;
- 2)在推送时机上:算法会根据用户的偏好和个性化行为数据,计算每个用户的个性化推送时间,在用户空闲的时间推送(避免在不合适的时间打扰用户,同时也能提升用户看到推送的可能性)。
- 3)在推送素材上:算法会根据素材的实时点击反馈,对素材做实时赛马。只发用户感兴趣的素材,提高用户点击意愿。
9、实际优化效果
通过以上我们的分析和技术优化手段,整体弱推送链路链路有了不错的提升,离线消息的到达率相对提升了两位数。
10、写在最后
本篇主要和大家聊的是只是IM消息系统链路中的一环——弱感知链路的优化,落地到到具体的业务也就是离线消息送达率问题。
整体IM消息系统,还是一个比较复杂的领域。
我们在消息系统的发展过程中,面临着如下问题:
- 1)如何进行消息的链路追踪;
- 2)如何保证IM消息的快速到达(见《闲鱼亿级IM消息系统的及时性优化实践》);
- 3)如何将消息的玩法和底层能力分离;
- 4)离线推送中如何通过用户找到对应的设备。
这些问题,我们在以前的文章中有所分享,以后也会陆续分享更多,敬请期待。
附录:相关资料
[1] Android P正式版即将到来:后台应用保活、消息推送的真正噩梦
[2] 一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践
[3] 一套亿级用户的IM架构技术干货(上篇):整体架构、服务拆分等
[4] 一套亿级用户的IM架构技术干货(下篇):可靠性、有序性、弱网优化等
[5] 从新手到专家:如何设计一套亿级消息量的分布式IM系统
[6] 企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等
[8] 移动端IM中大规模群消息的推送如何保证效率、实时性?
[10] 新手入门一篇就够:从零开发移动端IM
[11] 移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”
[12] 移动端IM开发者必读(二):史上最全移动弱网络优化方法总结
[13] IM消息送达保证机制实现(一):保证在线实时消息的可靠投递
[14] IM消息送达保证机制实现(二):保证离线消息的可靠投递
[16] 零基础IM开发入门(二):什么是IM系统的实时性?
[17] 零基础IM开发入门(三):什么是IM系统的可靠性?
[18] 零基础IM开发入门(四):什么是IM系统的消息时序一致性?
本文已同步发布于“即时通讯技术圈”公众号。
作者:Jack Jiang (点击作者姓名进入Github)
出处:http://www.52im.net/space-uid-1.html
交流:欢迎加入即时通讯开发交流群 215477170
讨论:http://www.52im.net/
Jack Jiang同时是【原创Java
Swing外观工程BeautyEye】和【轻量级开源移动端即时通讯框架MobileIMSDK】的作者,可前往下载交流。
本博文
欢迎转载,转载请注明出处(也可前往 我的52im.net 找到我)。
以上是关于阿里IM技术分享:闲鱼亿级IM消息系统的及时性优化实践的主要内容,如果未能解决你的问题,请参考以下文章