转: 58同城高性能移动Push推送平台架构演进之路

转: http://geek.csdn.net/news/detail/58738css

 

文/孙玄程序员

本文详细讲述58同城高性能移动Push推送平台架构演进的三个阶段,并介绍了什么是移动Push推送,为何须要,原理和方案对比;移动Push推送第一阶段(单平台)架构如何设计;移动Push推送典型性能问题分析解决,以及高可用、高性能、高稳定性如何保证。安全

什么是移动Push推送

移动Push推送是移动互联网最基础的需求之一,用于知足移动互联环境下消息到达App客户端。以转转(58赶集旗下真实我的的闲置交易平台)为例,当买家下单后,咱们经过移动Push推送消息告诉卖家,当卖家已经发货时,咱们经过移动Push消息告诉买家,让买卖双方及时掌握二手商品交易的实时订单动态。bash

为何须要移动Push推送?

移动互联网络环境下,常常会出现弱网环境,特别是2G、3G等网络环境下,网络不够稳定,App客户端和相应服务器端的长链接已经断开,消息没法触达App客户端。而咱们业务须要把Message(转转App交易消息等)、Operation(转转App运营活动等)、Alert(转转红包未消费提醒等)等消息推送给App客户端,从而触发用户看到这些消息,经过点击这些Push消息达到相应目标。服务器

推送原理和方案对比

移动Push推送主要有如下三种实现方式。网络

  1. 移动App轮询方式(PULL) 
    App客户端按期发起Push消息查询请求,来达到消息推送的目的。PULL方案的优势和缺点都比较明显,总体架构简单但实时性较差,咱们能够经过加快查询频率,提升实时性,但这会形成电量、流量消耗太高。
  2. 移动App基于短信推送方式(SMS Push) 
    经过短信发送推送消息,并在客户端置入短信拦截模块,能拦截短信,并解析后转发给App应用处理。这个方案实时性好、到达率高,但成本很高。
  3. 移动App长链接方式(Push) 
    移动Push推送基于TCP长链接实现,消息实时性好,这是目前主流的实现方式,须要维护App客户端和服务端的长链接心跳,会带来额外的电量、流量消耗;在架构设计时,须要作些折中,以免流量和电量的大量消耗。此外Push推送技术架构复杂度较高,维护移动App客户端的海量长链接请求,并创建与App客户端通讯的加密通道,整合成内部少许有限的长链接,对通讯数据进行压缩与解压,以节省流量。

目前移动Push推送技术基本都是结合这3个方案进行,但对于不一样的移动终端平台,又有各自不一样的实现,这里详细介绍iOS和Android平台上的具体实现方案。多线程

iOS平台架构

对于iOS平台,因为其特殊性,移动Push推送相对简单,iOS应用是不容许service后台常驻的,因此你没有别的选择,也没办法经过开发本身的Push service来完成推送下发,只能经过苹果APNS方式来完成。iOS移动Push推送流程如图1所示。并发

图片描述

图1 iOS移动PUSH推送流程

 

Android平台异步

在Android平台上,因为对service常驻没有限制,可用的方案就多一些:能够经过Google官方C2DM 完成、开源方案(例如XMPP)、借助第三方,或者彻底自主研发的移动Push推送方案。 
Google C2DM的主要流程如图2所示。

图片描述

图2 C2DM移动PUSH推送流程

 

Google C2DM和Apple APNS流程大体相似,但其最大的问题是移动Push推送服务器在国外,很容易被屏蔽,并且Push推送延迟较大。此外因为 Android社区分裂比较严重,不少厂商直接就把C2DM模块给去掉了,因此在国内这个方案极不可靠,变成了一个理论上的方案。

移动Push推送开源方案

对于开源移动Push推送协议,常见的有XMPP等, 事实上Google的C2DM底层也是基于XMPP协议实现的,咱们经过线下测试发现,开源移动Push推送方案主要有两个问题:第一,没有ACK机制,消息到达没有保证,不可靠;第二,当移动Push消息请求量并发增大时,系统开始变得不稳定,甚至出现了模块宕机的状况。所以直接使用移动Push推送开源方案,也不是很是可靠,我我的建议:在大规模使用开源的移动Push推送方案以前,必须作到对开源技术方案总体把握住,否则一旦出现问题,没法及时定位和修复的话,带来的后果将会是灾难性的。

借助第三方移动Push推送方案

除此以外,目前移动Push推送市场上,还有很多第三方推送产品可供选择,但须要面临如下几个问题:

  • 到达率 
    虽然第三方移动Push推送产品都宣传到达率高于90%,可是实际使用起来,发现远远达不到。固然到达率低的问题,除了第三方移动Push推送平台自己技术缘由外,还和业务推送方的用户选取有很大关系,若是用户较活跃,到达率就会高些,若是用户不活跃,或者用户已经卸载了相应的App客户端,必然形成到达率进一步下降。

  • 实时性&控制度 
    第三方移动Push推送产品的推送通道是共用的,会面向多个推送客户,若是某一个客户Push推送量特别大,那么其余的消息实时性可能就会受到影响,这些都是业务推送方不可控的,会比较被动。

彻底自主研发的移动Push推送方案

咱们曾经考虑实现一套彻底自主的移动Push推送平台,若是从零开始来作,须要解决几个难点:第一,移动Push推送服务端对移动App客户端海量长链接的维护管理。第二,App客户端常驻 service稳定性,如何使Push service常驻?咱们能够借助父子进程互相监控的方式来作到,一旦发现对方进程不在了,会从新创建,继续循环监控。第三,手机内存不足时,系统会杀掉Push service,甚至有些操做系统比较强势,它会向iOS系统同样并不容许第三方Push service 常驻。第四,移动Push推送到达率的提升,除了技术手段外,还有一些PR的手段,好比移动App客户端Push service经过在相应操做系统上添加白名单的方式使其永久常驻。总之,在移动互联复杂的场景下如何让移动Push推送到达率变得更高,不是一件简单的事儿。

58同城移动Push推送方案

咱们综合考虑前面讲述的开源、基于第三方、彻底自主研发方案,58同城并无选择从零开始彻底自主研发而是采用了基于第三方移动Push推送平台和自主研发高性能Provider的方案(如图3所示),知足天天百亿量级的吞吐量,并经过动态组合和扩展的方式,结合离线的移动Push推送数据分析,不一样手机使用不一样的推送策略,针对性地优化。在Android平台,咱们融合多种第三方移动Push平台,从而有效提高到达率。

图片描述

图3 58同城移动PUSH推送平台技术架构

 

第一阶段(单平台):架构如何设计

背景&需求

2011年咱们研发了58帮帮,这是一款知足58用户和商户之间沟通的即时通信软件,用户间能够互相添加好友、收发消息等。58帮帮的消息推送基于App客户端和服务器的长链接,一旦这条长链接断开,那么IM服务端的消息将没法推送给App客户端,用户也没法看到这些消息。在iOS平台上,58帮帮App切换到后台后,App与IM的长链接断开,消息没法触达,这时候咱们须要借助iOS APNS机制,IM消息须要发送给APNS,APNS再转发对应的消息到58帮帮App。Android切换至后台,App与IM的长链接保持,IM消息能够正常推送,所以在这个阶段咱们须要解决的问题是在iOS平台上,当58帮帮App切后台后,IM在长链接断开后的消息触达需求。

设计目标

基于上述的背景和需求,咱们在设计移动Push推送第一阶段(单平台)架构时,首先要知足在iOS平台上,当IM长链接断开后,IM消息的可以触达到App客户端。其次咱们的移动Push推送协议设计也具有很好的扩展性,在能够预见的将来,Push推送平台将逐步接入更多的App,所以咱们设计目标iOSProvider是一个通用的iOS推送服务。不一样App经过使用不一样的移动Push推送证书借助同一iOSProvider完成移动Push消息推送,对于不一样App的接入,咱们采用了配置文件方式动态扩展接入,iOSProvider根据所配置App证书与APNS创建并维护多条TSL链接。配置文件的格式以下:

第一个域#第二个域#第三个域#第四个域

其中,第一个域为推送服务类型Type,以备扩展,1为APNS;第二个域为内部定义的APPID号,对应服务的App;第三个域为App的Apple证书文件名;第四个域为与APNS创建的链接数; 
每一个App接入的配置为一行,举例以下:

1 #88 #zhuanzhuan.p12 #64 1 #66 #58tongcheng.p12 #32

除此以外,iOSProvider须要对每一个接入App的APNS链接池进行管理,动态增删TSL链接,具有动态重连机制,并具备单独的反馈接收线程,用于异步接收APNS返回无效的Token,反馈给移动Push推送业务方,用于下次移动Push消息推送的优化。iOSProdiver根据Type、APPID选择对应的APNS链接,经过推送线程组装APNS包发送到APNS服务器,如图4所示。

图片描述

图4 iOSProvider架构图

 

第二阶段(多平台):架构如何设计优化

随着移动互联时代的到来,58同城研发了多个App,每个App都有移动Push消息推送的需求(消息、运营活动、过时提醒等),而且每一款App同时具备多个终端:Android版、iOS版等。在这样的需求背景下,咱们的移动Push推送平台须要继续演进,如何演进呢?

iOS移动Push推送通道能够很好的知足业务推送需求,但目前还不具有Android移动Push推送的能力,所以咱们急须要研发Android移动Push推送通道。如何作?综合目前可选择的方案,咱们选择了基于第三方推送平台以及自主研发高性能AndroidProvider的方案。

首先重点讲述针对Android移动Push推送的流程:第一,App客户端向第三方移动Push推送平台注册,获取对应的App惟一标示(Token)。第二,App将Token信息发送给AndroidProvider并集中存储,以便后续基于Token的移动Push推送。第三,AndroidProvider经过HTTPS或者TSL的方式和第三方移动Push推送平台创建链接,并把须要推送的消息发送到第三方移动Push推送平台。第四,第三方移动Push推送平台收到AndroidProver推送的消息后,会把此消息及时推送到App,从而完成整个推送过程,如图5所示。

图片描述

图5 Android移动PUSH推送流程

 

AndroidProvider子系统总体结构分为四个层次,第一层为业务方移动Push推送接入,用于众多移动Push推送业务方的接入。第二层为网络交互层,用于接收移动Push推送业务方的消息数据以及发送请求处理层的处理数据给业务推进调用。第三层为请求处理层,用于处理网络交互层放入请求队列的数据,组装成第三方移动Push推送接口须要的数据,经过HTTP或者HTTPS的方式调用下游的接口,并等待请求结果的返回,把请求返回的结果放入回应队列。第四层为第三方移动Push推送平台,由第三方提供,开放给使用方接口,供调用其功能,如图6所示。

图片描述

图6 AndroidProiver系统架构图

 

随着愈来愈多的移动App接入,移动Push推送需求趋向多样化,同时移动Push推送业务逻辑复杂化(多终端、批量发送、业务规则多样),公共策略每一个业务方重复开发(深夜防打扰功能、发送频率和发送速率的限制等),形成开发效率低下。为了解决这些问题,咱们抽象了公共的逻辑,并进行了统一的封装,对业务调用方透明,这些公共的逻辑包括:通用的策略和通用的控制,如图7所示。

图片描述

图7 Android移动PUSH推送演进业务架构

 

在移动Push推送第二阶段(多平台)阶段,咱们具有了Android、iOS的通道服务能力,知足推送消息的需求。可是咱们没有提供统一的发送接口,业务方须要各自组包(Android、iOS)发送不一样的推送通道,除此以外,推送通道性能方面还有待提高,推送通道稳定性还有待提高,此外推送通道包含了相对共同的业务逻辑,推送通道还不够“纯粹”。

第三阶段:架构和协议如何设计和优化

移动Push推送第二阶段还存在一系列的问题,所以在第三阶段须要解决,而且随着更多App接入,咱们须要提供公司级统一的高性能移动Push推送平台。基于第三方移动Push推送平台,咱们自主研发了知足天天推送百亿量级的高性能Provider,推送平台具有了高稳定性、接入方便,并提供了较高的推送到达率。

移动Push推送平台第三阶段咱们如何架构和设计?首先咱们知足对下游接入方多种链接的管理(HTTP、HTTPS、TCP、SSL、TSL),具有了多种链接动态伸缩性,从而知足Provider层对移动Push推送链接的要求。其次平台要具有高并发的特性,经过彻底异步的设计和多线程支持,作到了高并发和支持10万QPS吞吐量。再次咱们须要对接入下游的错误进行处理,一旦发现链接被断开等错误后,要可以自动使用新的链接,而且对已经发出还没到达App客户端的推送消息进行重发,以保证消息不丢失。第四咱们须要对通道进行封装,对外提供统一的友好接入接口,屏蔽底层iOS和Android接入的差别性。最后在Android移动推送方面,咱们接入了更多的第三方推送平台,以达到更高的到达率。

基于这些方面的考虑,58同城移动Push推送平台采用了低耦合的分层架构设计(如图3所示),分为三层Push Entry、Push Transfer、Provider(iOSProvider和AndroidProvider)。其中Push Entry是业务方调用的入口,咱们采用异步消息队列的方式,提供了较高的业务方发送的速度,而且具有了消息缓冲的功能,使得高峰期的海量移动Push消息推送对整个平台冲击较少,也起到了保护推送系统的做用。Push Transfer会从Push Entry层接收消息进行解析,对推送消息进行合法性检查,若是格式不合法,直接丢弃,同时会进行接收到的推送消息格式转换成内部的消息格式,分平台转发到iOSProvider或者AndroidProvider上;provider接收到Push Transfer的消息后,会按照下游须要的消息格式(APNS协议、Android协议)进行转换,进行消息的下发,在下发的过程当中,会进行消息的重发,以确保消息下发到第三方推送平台。

Provider模块内部如何设计?以iOSProvider为例,它分为三个层次:接入逻辑、业务逻辑、APNS出口。其中接入逻辑主要处理网络交互和请求分发;业务逻辑主要处理线程分裂扩展、并发处理和错误处理;APNS出口处理向APNS的发送逻辑,如图8所示。

图片描述

图8 iOSProvider模块结构图

 

对于移动Push推送平台来讲,追求达到率是咱们最核心的指标,没有之一。所以在Android方面,咱们融合了多个第三方推送平台,经过机型控制,对不一样的机型使用不一样通道,进一步提高推送到达率。AndroidProvider层进行消息推送策略的控制,先推送一通道,根据此推送通道ACK状况,是否继续推送其余通道。推送多个Push通道,会出现推送消息重复到达App客户端的情形,此时须要App客户端根据推送消息ID进行去重,收到的重复推送消息忽略处理。

典型性能问题分析解决以及高可用、高性能、高稳定性如何保证

在移动Push推送不断演进的过程当中,咱们遇到了AndroidProvider并发低的问题,仔细分析,是由于咱们采用HTTPS库,因为库中HTTPS的链接实现不是线程安全的,对每一个HTTPS的请求都加锁串行化处理,以保证线程的安全性。发现问题后,咱们经过在线上增长多进程部署的方式暂时解决,使得咱们有足够的时间分析此问题产生的根本缘由。通过深刻分析,发现缘由是咱们对HTTPS的库掌握不够,致使加锁粒度过大,经过HTTPS库提供的更小粒度的锁,咱们不只解决了线程不安全的问题,也提高了AndroidProvider的并发度,如图9所示。

图片描述

图9 HTTPS库细粒度锁实现方式

 

总之,58同城统一的高性能移动Push推送平台经过无状态化设计和冗余部署等方式确保了推送平台的高可用,经过纯异步、动态多线程的支持提供推送平台的高性能,经过质量保证、多种监控机制(进程监控、语义监控、错误日志监控、数据波动监控等),有问题及时发现处理保证了推送平台的高稳定性。

最后,我要感谢项目组的同窗,特别感谢姚劲同窗,有了大家持续不断的努力和付出,才有了今天这篇文章;也感谢老婆大人,有你在背后默默的支持,才有了今天这篇文章。


孙玄:58赶集集团系统架构师,技术负责人,技术委员会架构组主任,也是58同城即时通信、C2C技术负责人,负责58核心系统的架构以及优化工做。分布式系统存储专家,前百度高级工程师,参与社区搜索部多个基础系统的设计与实现。

本文为《程序员》原创文章,未经容许不得转载,订阅2016年《程序员》请点击 http://dingyue.programmer.com.cn

相关文章
相关标签/搜索