自如-端触达优化与实践

前言

实时的端触达能力在服务供给侧业务发挥重要的作用,年初公司服务运营同事反馈因为订单提醒不及时导致服务者接单超时的问题。生活服务团队在调研分析之后,采用了N+2推送渠道+前台服务保活的模式,统一封装推送组件,不仅实现了推送到达率的大幅度提升,还解决了推送接入复杂和统计数据不准确的问题,同时采取了订阅发布的模式实现了推送通知和长连接消息主题的统一管理。本文是对推送优化技术的总结和分享。

1.背景

自如服务者端在创建之初就接入了推送功能,以提高服务者的接单及时率。随着业务的发展和Android各家厂商系统对内存管理的优化,运营同事向我们反馈因为无法及时收到订单提醒,服务者的接单及时率在持续下降。经过分析,具体的原因是我们接入的是单一的第三方推送渠道。第三方的推送渠道受通用性的限制,无法通过Android系统推荐(通知栏显示常驻通知)的方式保活,只能通过各个应用互相拉起的方式进行灰色保活。保活效果低且不稳定。在单一渠道的情况下,进程存活且长连接保持是推送到达的前提。只接入单一三方渠道推送是服务者的提醒效果不理想的原因。

1.1问题与挑战

提升推送送达率我们想到了接入厂商渠道的方案。厂商推送由于端侧和云端的长连接是运行在系统进程中,这样我们的推送到达率就有了保证。但是推送率只是订单提醒的一个维度,厂商收到通知之后并不会启动通知推送的目标应用(这个做法也是基于内存和电量优化的考虑),这种情况下我们没有办法根据不同的推送类型来播放不同的音乐或口播提醒服务者。由于手机的系统通知铃声播放的音量和时长都不可控。所以这个方案只能解决送达率的问题,对提示服务者接单的效果也不理想。

我们在调研过程中还发现在服务者的业务场景中存在抢单池业务,抢单业务对消息触达的及时性要求更高。但是无论是厂商渠道还是三方渠道由于所有客户共用推送服务,在推送业务高峰期都会存在消息排队的情况。基于这种情况服务端同事决定自己搭建抢单消息的长连接服务。这样既能保证推送的及时率又能保证一旦出现业务故障,我们能够第一时间排查消息链路发现并处理问题。对于端侧来说自有长连接服务的上下行消息、三方渠道的推送消息和厂商渠道的通知这三个渠道注册机制不一致、承载的消息内容不一致、端侧消费业务方不一致、回执发送方不一致。

带着这些挑战,我们进行一系列的尝试和调研封装出我们的推送组件,这个过程中,我们总结出了一些经验,希望能给端侧的研发同学带来一些思路和帮助。

1.2上线后效果展示

承接的服务者订单提醒业务、单设备登录验证业务效果展示

推送组件功能演示>>

2.技术调研

基于以上需求点,我们分析了市场上主流的三方推送渠道和厂商推送渠道。其中主流的几家推送供应商提供了厂商推送的集成能力,但是他们没有暴露自身的长连接接口,无法使用他们的长连接渠道收发我们的自定义消息。包括VIP收费用户也没有相关的功能。

【调研结论】

市面上的推送供应商都无法满足我们的业务需求。我们需要封装一个推送组件来整合多个推送渠道并且整合我们自由的长连接服务。来实现不同类型不同业务方的消息按照优先级通过多种渠道触达用户。

【推送流程分析】

diagram-9185299933283324243.png

【建立连接】

建立连接过程是打通推送闭环的最关键的一环,封装推送组件之前。端侧会通过推送供应商SDK中提供的api来设置别名,别名一般使用服务者的uid或者登录账号的MD5摘要值。进行推送时,我们的业务后端将别名数组和推送数据给基础平台,然后基础平台把别名和数据转发给推送供应商,推送供应商再通过别名查找出设备的cid,然后通过cid识别出设备并发送消息。

这个过程存在两个问题:

如果我们使用uid当做别名,推送供应商就拿到了我们的业务数据,这个是不合适的。

将cid和别名的映射关系维护在推送供应商侧,整个查询过程不可控。在实践中我们也验证了这个问题,通过别名群发消息时会出现丢消息的现象。

【端侧消息处理】

封装推送组件之前,我们直接在推送供应商SDK提供的消息回调方法中处理了消息。现在我们app端承载的业务已经很庞大了,并且随着组件化的落地,app内的业务相关度和耦合度都非常低。如果在一个方法中来处理所有业务线的所有消息。这个类将会非常的庞大,判断逻辑也会多层嵌套。

【端侧回执上报】

封装推送组件之前,我们的端侧回执上报是缺失的。这导致我们的推送送达率不准确。推送供应商统计的送达率也不理想。

经过分析我们将工作的重点放在建立连接、端侧消息处理和端侧回执上报三个方面。

3.框架设计

1610628557473.jpeg

推送渠道提供推送别名绑定方法、推送别名解绑方法供业务方调用。推送渠道控制器整合了推送SDK的常用的API。BasePush根据Controller中的方法抽象出各个渠道SDK的方法供PushManager调用。

【消息拦截器】

参考okhttp拦截器的实现方式,对各个消息进行预处理。这个消息不只是推送的消息,还有消息处理器发出的SDK初始化结果消息、别名注册结果消息,方便对整个组件工作状态的上报和日志输出。同时消息回执也是在拦截器中执行的。

【消息处理器】

消息处理器中统一对不同的消息做出处理。如果随着业务发展有更复杂的逻辑,这儿可以设计一个状态机,根据推送组件不同的状态和收到不同的消息两个维度,对消息做出不同的处理。

【消息订阅管理器】

在前面调研中提到,组件化下端侧业务规模越来越庞大,并且业务之前的耦合度低。同时长连接消息会以页面为粒度来订阅、取消订阅消息。理想的方式应该是订阅模式,每个业务方或者页面只订阅自己需要的主题,不关心也不处理其他主题的消息。我们使用Subject来管理消息。不同的业务方可以订阅不同的Subject,订阅之后只会收到对应主题的消息。这样就实现了上述效果。

【订阅方式】

暴露一个IRouter接口,将实现这个接口的对象注册到PushRouter,这样就可以在任何一个界面收到Push或长连接消息了,也可以在任何时机注销接收者,注销之后就不会收到相关的推送了。

5.推送组件在服务者三端、ZO、ZE中落地实践

deliverability.png

服务者三端都截图了推送组件,接入之后推送到达率有很大提高。

端的平均接入时间1.5pd,接入推动能力的成本降低。

6.后期优化方向

实现推送组件的自动初始化,实现新业务线两行代码接入推送能力

使用ContentProvider承载推送组件初始化工作,实现推送组件的自动初始化。

电量消耗优化

在单独的保活进程中处理推送和长连接逻辑。避免主进程长时间存活增加耗电量。

7.本文小结

本文阐述了推送组件将三方渠道、厂商渠道以及自有长连接融合来提升端侧触达能力。解决了单一通道送达率低的问题和支撑了业务消息快速触达端侧。也实现了新业务线推送能力的快速接入。

作者:自如大前端研发中心-服务研发组-刘彬

招聘信息

自如大前端研发中心招募新同学!

FE/IOS/Android工程师

公司福利有:

  • 全额五险一金,并额外购买商业保险
  • 免费健身房+年度体检
  • 公司附近租房9折优惠
  • 晚间打车报销
  • 每年2次晋升机会

欢迎对技术有执着热爱的你加入我们!简历请投递 zhangxl122@ziroom.com, 或加微信 v-nice-v 详聊!

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享