查看原文
其他

京东大规模消息推送平台搭建实践

点击上方“开发者技术前线”,选择“星标”

在看 真爱

来自:京东技术团队


背景


每个app或者业务都有将信息推送到用户客户端的需求。作为中台的推送平台,需要为公司内部许多个不同app同时提供可用,稳定的推送服务,因此我们消息推送平台应运而生。


推送平台架构


名词解释:

dt:全称deviceToken,代表设备唯一标识。

appId:用户在推送平台申请的应用代号。

token:平台上每个应用对应的专属密钥。

msgId:每次推送调用,平台生成的消息唯一标识。


平台侧服务:

send-pservice:对外提供推送平台网站,用户可以在网站上进行申请应用,创建推送,查看数据等操作。

send-api:对外提供接口服务,包括JSF和http两种方式,接口包含推送,解绑,注销等。

send-worker:主要负责拉取定时推送,进行发送。


通道侧服务:

habitat:负责设备数据库的相关操作,包括绑定,解绑,上报,注销等。

mutate:负责接收推送请求,处理推送的pin,dt对应关系,及推送通道的适配。

report:上报服务,负责接收设备首次登录时,生成的dt上报。

channel:负责发送最后的推送请求到各个推送通道。

slark:回执服务,负责接收部分厂商通道推送后的异步回执信息,并做后续处理。


其他:

自建通道:由平台搭建的推送通道服务,负责维护长连接,推送消息到客户端。

厂商通道:由外部厂商提供的系统级推送服务。

DataAnalysis:平台的数据统计服务,负责统计推送的流转数据。


业务方进行推送有两种方式,一个是通过推送平台网站在页面上创建推送,第二个是通过调用我们提供的api服务的方式,进行推送。推送类型分为广播和指定用户推送,用户可用在创建推送的时候指定类型,指定人群或者设备。

平台内部收到消息推送的请求后,请求内如果是以设备形式推送,系统会直接将推送内容和dt组合,推送给推送通道。如果请求是以人群pin方式推送,系统通过pin找到对应的所有有效设备,然后以内容加dt的方式进行推送。推送通道分为两种,自建通道和厂商通道。厂商通道是手机或者系统的厂商提供的系统级别推送通道,由手机系统维护,相对稳定。自建通道是我们自研的推送通道服务,通过自建通道服务与客户端之间维持的长链接,对在线设备进行推送。


关键数据准备


在应用维度,消息推送平台是为不同的app提供推送服务,所以需要为每个app生成appId以及对应的token,用于业务方调用推送平台认证使用。

在设备维度,平台会存储dt,pin和appId的对应关系,用于具体推送消息的组建以及设备数据的维护。



在消息维度,平台对于每次业务方推送请求的调用,生成一个msgId,并返回给调用方,这个msgId会在整个推送过程中被携带,从推送平台生成,推送到自建或者厂商通道,触达到客户端,最后回执给推送平台。这种方式是对整个推送流程追踪的必备条件,方便排查问题和推送数据统计。


关键技术环节


1推送请求的处理

业务方推送可以通过平台页面创建,和调用send-api服务接口两种方式,后者的使用较为频繁。平台提供http和JSF两种接口调用形式,推送请求按照实时性分类,可以分为即时推送消息和定时推送消息。

对于要求即时推送的消息请求,api服务在接到有效调用后,会立即调用通道侧的推送接口进行推送。对于需要定时推送的消息,api服务会将任务写到redis的有序集合中。send-worker会定时拉取各个应用集合中的推送任务,并将到达推送时间的任务取出,进行封装,调用通道侧服务进行推送,得到成功回执后,将任务移除。



为了提高接口性能,除基础参数校验之外,其他请求处理流程均采用异步方式。使用线程池执行每次推送请求的处理过程,缩短响应时间。这样可以减小高并发大量请求时,因响应时间过长,导致的响应超时或者JSF线程池耗尽的情况发生。

2请求厂商通道

通道侧在收到平台侧封装好的推送请求后,会筛选出dt,然后将消息内容体和dt组合在一起,去请求厂商通道。如果业务方传的是pin,系统则会根据对应关系定位到pin对应的dt集合。当有厂商回执清理dt,或者业务方调用解绑或者注销dt接口时,这个dt集合是动态实时更新的。对于一次推送到大量dt的相同消息体,也就是群推或者广播的情况,系统会将dt分组发送,以控制请求体的大小。



在高并发请求的情况下,请求厂商通道很可能出现厂商限流导致失败的情况。当请求失败出现后,系统都会去进行重试,但是这个时候的重试如果时间间隔太短,其重试是无意义的,厂商通道在这么短的时间内可能还是限流状态,重试间隔如果太长,又会降低请求的效率,还消耗系统的内存。

因此推送平台对于这种情况采用了可配置的重试策略,实现对重试的次数和重试时间间隔的动态调整配置,方便根据厂商通道的具体情况对重试机制进行热更新。

3长连接的建立与维护

自建通道是消息推送平台自己搭建的长连接推送通道服务,目的是为无法接入厂商通道的设备提供有效的推送途径。


长连接的建立:

自建通道的长连接是基于TCP+TLS实现的。当客户端上线动作触发时,会向服务端机器发送请求,服务端接收到请求之后,会返回给客户端一个心跳参数,这个参数会作为双方无数据交互时的心跳间隔。此后,客户端在正常情况下,如果与服务端没有数据交互,也会定时发送心跳至服务端,双方长连接建立成功。

我们会根据实际的网络及服务器情况,动态适配heartbeatConfig参数,包括断开时间间隔Idle和心跳发送间隔heartbeat,都可以进行动态调整。


长连接的维护:

客户端的第一次请求触发onConnect动作后,服务端会把客户端ctx与自建通道集群的连接关系维护起来。当双方在Idle时间内既无数据交互,又无心跳链接时,服务端会判定该客户端下线,对应长连接已断开,客户端的所有连接记录会被自动解除。

在长连接过程中,可能出现网络断开导致客户端断连重连现象。即在Idle时间内,同一个客户端向服务端请求第二次建连,这时可能出现一个客户端与服务端建立两个长连接的情况。对于这种问题,服务端采用断开老连接,接受新连接的形式,保证集群中每台设备长连接的唯一性。


使用长连接进行推送:

当通道侧的channel服务受到最终的推送请求后,会将消息体和dt最终封装成请求通道的形式。对于使用自建通道的设备,channel会自动识别到该设备对应的服务器单机ip,将推送请求发送到对应机器进行推送。识别不到则判定设备不在线,无法进行推送。



自建长连接的安全保障:

对于自建通道的长连接服务来说,安全性是十分重要的。我们主要从两方面对安全性做了保障。第一个是自建通道使用TLS加密的服务端域名。第二个是使用自定义的编解码方式,在服务端和客户端SDK之间,我们统一使用事先规定好的自定义编码和解码方式,来提高数据层面的安全性。

4推送回执的处理

每个厂商通道包括自建通道的回执参数标准都不统一,平台的slark服务用于接收推送通道的回执消息,目前接入回执服务的厂商包括华为,魅族,小米和OPPO。针对不同的通道,平台会根据每个通道的回执参数标准,为每个通道做单独的回执信息处理,例如根据返回码进行无效dt的清理,客户端打开推送后的流水发送(用于数据统计)等。


平台数据统计


1消息维度数据

推送数据对于一个推送平台来说必不可少,这些数据既可以用于每个业务方查看自己每条推送的状态效果,方便他们更好的制定推送策略,同时也让每条推送有迹可循,方便了推送整个流程的问题排查。

推送状态包括处理,发送,触达,打开。消息处理和发送两个状态由通道侧处理节点生产到kafka,消息的触达和打开由SDK上报给厂商或者自建通道,再由通道回执给slark服务,生产到kafka。



推送平台对于消息推送提供了多维度的数据统计,包括对每台设备,每个用户的推送记录,还有群推和广播各个环节的总体数量统计,并体现触达率和打开率。



同时,还提供了推送通道维度的推送状况统计,以及近期推送走势图,可以让业务方从多个角度,清晰准确的观察到自己每条推送的结果。


2设备维度数据

设备数据方面,平台除了保存每条dt的详细对应关系外,还对于每个应用的设备总量,每日的新增设备,清理设备,关闭设备进行了单独统计和展示。同时也提供了手机品牌(安卓),型号(IOS)维度的设备数据统计。



3数据统计的实现

技术实现方面,数据的统计使用了flink计算程序,通过全流程携带的msgId,消息类型,推送状态以及客户端上报的设备类型等字段,计算出各个维度的推送数据。在每台设备这个维度的推送数据方面,使用了elasticSearch,对推送数据的必要字段进行了落地,支持用户以pin的形式,查询对应所有设备的推送情况。



监控与报警


对于一个成熟的平台化产品,对于自身业务及服务的监控和报警必不可少。消息推送平台在内部系统,用户使用需求两个方面都设置了详细的监控埋点,制定了可靠的报警规则。

在内部系统方面,推送平台针对每个新建的应用都添加了appId对应的接口埋点监控,当接口的调用量,性能,可用率发生变化时,平台管理员会根据报警,找到对应的应用负责人,方便及时的了解情况,定位问题,解决问题。同时也对关键集群中的机器设置了内存,CPU报警规则,及时监控服务端集群性能。

此外平台还对于每个应用所上传的证书进行每日定时检查。由一个定时任务程序每天拉取所有应用证书,解析证书有效期,平台会对已经失效,或者还剩7天失效的证书应用负责人进行邮件,短信等形式的报警,以敦促用户尽快更换证书,避免问题出现。


平台未来规划


提升系统性能,扩大服务范围:

目前消息推送平台已经为京东金融,京麦,京喜等应用提供消息推送服务,下一个目标就是为京东主站提供全量消息推送的服务。我们也将继续优化性能,提高系统的稳定性和可用率,打造一个优秀的大规模分布式消息推送平台。

与此同时,消息推送平台还将推进对外输出的工作。将上云,组件化的相关改造任务尽快完成,让推送平台可以对外赋能,服务到公司外部更多的用户群体。


在公众号,在后台回复关键字:666,可以获取一份程序员大礼包!




END

好文点个在看吧!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存