移动互联网时代,推送(Push)服务成为App应用不可或缺的重要组成部分。推送服务可以提升用户的活跃度和留存率。
然而,市场现有推送服务一直存在不少问题。
第一、耗电。手机耗电量大,手机电池坚持不了两天,待机时间短;
第二、不稳定。消息丢失、重复推送、延迟送达、过期推送时有发生;
第三、无用消息,用户收到的大量无用消息,垃圾信息满天飞。
这些问题让用户很受伤。用户很生气,后果很严重,用户可能直接就把应用卸载了,真是成也萧何,败也萧何。
京东云推送是京东云平台推出的节省、稳定、精准的推送服务。针对耗电、不稳定、无用消息等问题,京东云推送做了的周全的处理。本文将尝试分析京东云推送如何解决市场现有推送服务存在的上述问题,实现节省、稳定、精准推送。
使用传统推送服务,手机上多个应用都使用推送服务时,耗电量大,手机电池坚持不了两天 ,待机时间短。手机推送原理,就是通过建立一条手机与服务端的连接链路,即长连接,当有消息需要推送到手机时,通过这条链路发送消息。长连接需要定期发送心跳来确保链路一直保持,这都有电量和流量消耗。比如有5个应用都使用了某推送服务,每个应用都和后端服务器建立长连接,并定期发送心跳包,耗电、流量情况可想而知。
省电省流量。京东云推送设计多应用单服务单连接模式、使用AlarmManager定时心跳节省电量和流量。
多应用单服务单连接。手机上多个App应用共享一个Android服务一个连接。京东云推送设计了多应用单服务单连接模式。手机上多个应用使用了京东云推送,即每个应用内嵌入了京东云推送SDK,多个应用共享一个服务JDPushService,由Service去和云端服务器建立TCP长连接,接收消息。
每个终端设备在云推送平台有一个唯一标识Token,每个应用有唯一标识AppID. JDPushService收到云端消息后,根据消息包里的AppID,来判断消息属于哪个App后发送给对应的App应用。第一个应用启动了推送服务后,其他应用启动服务的时候,会检查服务是否存在,如果存在就使用已启动服务。每个应用都有机会启动JDPushService服务,运行推送服务增加的耗电量和流量总体上会比较平均地分摊到各个应用上。多应用单服务单连接,有效解决了多应用多链路带来的高耗电费流量问题。单个手机上使用京东云推送服务的应用越多,省电省流量优势就越明显。
AlarmManager定时心跳。京东云推送使用AlarmManager来定时执行心跳任务。长连接通信,如果连接一段时间没有通讯数据时,链路一般会被切断。为了防止链路中断,需要发送心跳维持存活。Android手机上使用Timer 执行定时任务时,需要用WakeLock让Cpu 保持唤醒状态,会大量消耗手机电量,缩短手机待机时间。而用AlarmManger来执行定时任务,Cpu可以正常休眠,只有在需要运行任务时醒来很短时间,极大的提升手机的待机时间。
节省服务器。京东云推送单服务器能够支撑200万(C2000K)以上的连接数。单服务器承载同时连接数越多,所需服务器就越少,成本越低。保证大量的在线连接稳定可靠地通信,对后端连接服务器有很大挑战。如何提升单服务器连接数,保证连接稳定可靠的推送数据,是推送服务的技术难点。
Object pool缓存可重用的对象。会话服务器上承载了大量的终端连接,每个Session连接处理、心跳包、回执、命令处理的结构和过程都是一样的,京东云推送使用Object pool缓存一组可重用的对象,减少了频繁动态创建对象带来的内存分配和回收资源消耗。和动态分配内存相比,分配和回收速度快很多。另外,对每个对象和处理细节,充分优化内存使用,持续优化。内存瓶颈会限制服务器能够接入的用户连接数,通过Object pool 、各处理对象细节优化,极大提升了内存使用效率。
多核并行化。将任务调度到服务器所有Cpu核心上,并行处理。会话服务器上承载了大量的终端连接,Session会话连接和消息处理时,尽量充分利用现代服务器普遍具有的多核特性,将任务并行化,将所有任务调度到所有CPU核心上,最大化的利用服务器多核计算能力,从而提升推送服务整体性能。
市场现有推送服务一直存在消息丢失、重复推送、延迟送达、过期推送等诸多问题,京东云推送针对这些问题,做了周详处理。
消息丢失问题主要原因有网络不稳定、系统可用性差等问题引起。国内手机网络不是太稳定,上网方式复杂众多,覆盖范围也不是很全,另外用户还经常使用WIFI上网。网络信号经常时好时坏,网络不稳定造成消息丢失或丢包都是正常的。
不丢消息。京东云推送通过消息回执确认机制、高可用分布式服务器集群确保不丢消息。
消息回执确认。用户终端每收到一条消息,会给云端发送回执确认。消息发送给用户终端应用后,终端JDPushService服务发送收到该消息的回执确认给云端服务,云端把消息状态置为已送达。手机网络不稳定造成长连接中断时,JDPushService向云端服务发起重连时,如果未收到回执确认并且消息未过期,云端会重新发送该消息给用户终端,确保即使网络不稳定 ,用户始终能收到消息。
为了防止应用重复收到同一条消息,终端JDPushService服务对最新消息做持久化,收到消息时判断是否已收过该消息,如果未收过就发送给应用,否则不再发送。同时发送回执给云端,有效解决重复推送问题。
高可用分布式服务器集群。系统可用性差也会造成消息丢失,比如消息发送处理中,系统出现意外,就有消息丢失可能。京东云推送云端采用分布式服务器集群架构,每个服务节点没有单点,确保系统的高可用。各个实例节点间通过MQ通信,对每个job是否成功的反馈确认,如果worker节点在执行job时崩溃或者退出,该job会再分发给其他woker节点执行,确保消息处理环节不丢失。数据存储集群提供完善的数据备份和故障转移支持,确保数据在存储环节不丢失。
实时送达。京东云推送点播消息1秒内送达用户终端。市场现有推送服务,消息从发出到用户收到消息时间过长,用户无法第一时间收到消息,推送不实时。京东云推送终端应用启动推送服务时,会启动一个后台共享服务JDPushService,由该服务和云端服务建立长连接。云端服务通过这条链路,有消息时实时推送消息到用户终端。移动网络很不稳定,如果TCP链接出现中断,JDPushService服务会重新发起连接,保证通信链路一直可用。JDPushService是后台服务,即使应用退出后,服务仍然可以接收应用消息并通知用户,确保应用即使在线离线状态下,也能实时收到最新消息。
耗时任务分解。单服务器处理能力是有限的,耗时任务拆分成多个子任务,多台服务器同时并行处理,提升时效。比如给5000万用户发送一个广播消息,需要把消息任务分解成多个子任务,多服务器同时并行处理,有效缩短消息发送处理时间。
有效期推送。京东云推送设计消息过期失效机制,确保只推送有效期内消息。消息具有时效性,过了某个时间点的消息对用户来说就失去了价值,同时还影响体验。比如用户关机一个月后开机启动应用后,瞬间收到一个月的所有消息,用户手机瞬间瘫痪。京东云推送对消息设置离线保存时间,如果超过离线保存时间,消息自动失效并置为历史消息,不再对用户推送。比如设置离线保存72小时(默认2天),发送消息时用户没有开机,两天后用户开机并启动推送服务,这时不会收到已过期的消息。
精准推送。京东云推送提供精细化的标签组播推送和点播推送。现有推送用户经常收到的大量无用消息,垃圾信息满天飞。应用内广播每个应用终端用户都能收到,但是未必每个用户都需要。京东云推送提供了标签组播和点播功能,开发者可以根据用户的习惯、爱好、对特定产品偏好程度等给用户设置标签。用户使用App某个预设操作时,调用京东推送SDK标签绑定接口,给用户绑定标签。应用商需要对该类用户推送特定消息时,调用标签组播推送接口,京东云推送会定位到绑定了该标签的所有用户,并把消息实时推送给用户。标签设置粒度越细,推送的精准度越高。如果需要对某个特定用户推送消息,可以使用点播功能推送消息。通过用标签组播和点播功能,消息只推送给感兴趣的用户,实现消息精准推送。
京东云推送通过多应用单服务单连接、AlarmManager定时心跳,省电省流量;Cache pool 、多核并行化提升后端服务器单机处理能力,节省服务器;消息回执确认机制、高可用服务器集群确保不丢消息;终端服务已收消息过滤防止消息重复推送;Android后台服务长连接、云端耗时任务分解并行处理,实现实时送达;离线消息过期时间设置确保消息有效期内推送;精细化标签组播和点播有效提升消息推送精准度。京东云推送通过这一系列策略、技术实现,为开发者提供一个节省、稳定、精准的推送服务。
作者简介:康新荣,京东云平台资深架构师,云推送项目研发负责人。10年IT行业研发经验,在云计算、NoSQL、分布式、高并发系统构建等领域有丰富的经验。