今科科技旗下 NEEQ:837882
行业资讯 | 基于APNs最新HTTP/2接口实现iOS的高性能消息推送(服务端篇)
专栏:科技资讯
发布日期:2018-08-25
阅读量:8348
收藏:
1、前言本文要分享的消息推送指的是当iOS端APP被关闭或者处于后台时,还能收到消息/信息/指令的能力。这种在APP处于后台或关闭情况下的消息推送能力,通常在以下场景下非常有用:1)IM即时通讯聊天应用:聊天消息通知、音视频聊天呼叫等,典型代表有:微信、QQ、易信、米聊、钉钉、Whatsup、Line;2)新闻资讯应用:最新资讯通知等,典型代码有:网易新闻客户端、腾讯新闻客户端;3)SNS社交应用...
1、前言本文要分享的消息推送指的是当iOS端APP被关闭或者处于后台时,还能收到消息/信息/指令的能力。 这种在APP处于后台或关闭情况下的消息推送能力,通常在以下场景下非常有用:
除了以上典型场景下,消息推送这种能力已经被越来越多的APP作为基础能力之一,因为移动互联网时代下,用户的“全时在线”能力非常诱人和强大,能随时随地即时地将各种重要信息推送给用户,无疑是非常有意义的。 众所周之,iOS端的这项消息推送能力就是使用苹果提供的APNs服务来实现(有些iOS小白开发者可能看到各种第3方的iOS端消息推送SDK,总会习惯性地认为这是完全由第3方提供的能力,实际上同样是使用APNs,只是封装了一下而已)。目前介绍APNs消息推送的文章多讨论的是手机端的实现,而服务端的消息要怎么“推”出来这样的文章,要么太老,要么只是介绍如何调用第3方的服务端SDK接口而已(如极光推广、友盟推送、腾讯信鸽推送等)。所以本文趁着最近对项目组的老苹果iOS推送进行升级修改机会,详细查阅了最新苹果的APNs接口文档,同时为了避免重复造轮子(懒),在调研了一些开源常用的库之后,选择了Turo团队开发和维护的pushy开源工程来实现在Java服务端调用苹果最新的APNs HTTP/2接口进行消息推送,并借此文对Pushy的使用方法进行了总结和记录,希望对你用。 补充说明:网上目前能查到的有关iOS端APNs消息推送的Java服务端代码实现,多是介绍如何使用Java-APNS这个工程,但这个工程以及类似的其它工程都很久没有维护了,跟最新的苹果APNs服务已经很难匹配了。相较而言puhsy这个工程一直比较活跃,也对苹果的最新APNs跟进的比较及时,因而本文作者在公司的项目进行升级和重构过程中,毫不犹豫的使用了pushy。 学习交流:
(本文同步发布于:http://www.52im.net/thread-1820-1-1.html) 2、相关文章有关iOS客户端APNs消息推送技术的介绍文章:
有关消息推送技术服务端架构方面的文章:
3、提一下Android端的消息推送论坛里做IM或消息推送服务的朋友都很清楚,相对于苹果为iOS包办好的APNs技术,Android上的消息推送技术乱七八糟、一塌糊涂,原因是国内的Android厂商将Android原生的GCM(现在叫FCM,跟iOS的APNs是类似的技术)进行了阉割,加上各厂商的省电策略、这全策略各不相同,导致为了实现IM和其它各种应用中的后台消息推送,不得不为了进程保活、网络保活搞出各种黑科技(当然,自从Android 6.0发布以后,谷歌为了打击这种不道德的行为,进行了越来越严格的限制,保活黑科技越来越难搞了)。 国内的厂商为了跟进新版本Android的GCM(现在叫FCM),也都在搞自已的消息推送通道:小米手机有小米推送、魅族手机有魅族推送、华为手机有华为推送等等,开发者在放弃保活黑科技以后,只能一家一家接入各厂商的推送通道,而这这又涉到同一厂商的手机版本、不同厂商通道的自动识别等,麻烦事乱到你无法想象,就连第3方推送服务也只能就范——一家一家接入(比如信鸽的《[资讯] 信鸽新版上线:号称Android首家统一推送服务》)。 为了解决上述乱象,好消息是去年有政府背景的“统一推送联盟”成立了(详见《[资讯] 统一推送联盟在京成立:结束国内安卓生态混乱》),广大Android开发者真是翘首以盼,但坏消息是好进展并不顺利(大家心知肚明啊,各厂商的利益不好均衡嘛),最近一次跟消息推送服务有关的活动还是3个月前的《[资讯] 统一推送联盟2018成员大会如期召开》。虽然进展不大,但总算还是有希望,Android同行们再等等,总有Android端消息推送一统江湖的方案出现的那天。 当然,本文主要是讨论iOS端的消息推送,本节文字只是写给Android端消息推送感兴趣的同行看的,更多Android消息推送技术的文章,请前往:http://www.52im.net/forum.php?mod=collection&action=view&ctid=11 4、说一说为什么不使用第3方推送服务SDK?目前主流的iOS第3方推送SDK有:友盟推送、极光推送、信鸽推送等。 使用第3方推送的优点主要是: 1)简单:开箱即用,无需关注技术细节; 2)统计:提供了推送数据的统计能力等; 3)性能:无需关注性能负载,因为第3方都帮你实现好了,你只要调用它的接口即可。 使用第3方推送的缺点也很明显: 1)到达率:虽然第3方移动端消息推送产品都宣传到达率能够达到 90%及以上,但是实际使用起来,发现远远达不到; 2)实时性:第3方移动端消息推送产品的推送通道是共用的,会面向多个推送客户,如果某一个客户PUSH推送量特别大,那么其他的移动端消息推送消息实时性可能就会受到影响; 3)不可控:虽然各种技术细节无需你关注是个优点,但它也同时是个缺点——因为你不可控的东西太多了,想要做一个定制化的需求就力不从心了; 4)被限流:因为第3方的推送服务多是免费提供,所以接口调用等都是有限制要求的(即使纸面上没有说出来),限流是一定要做的,不然这些成本谁抗的住? 针对以上问题,58同城团队在《58同城高性能移动端消息推送技术架构演进之路》也有讨论。 更为关键的是,如果是实现iOS的消息推送,苹果官方提供的APNs服务已经足够简单,如果不是为了项目赶进度或偷懒,自已来实现是更靠谱的选择,简单的事情没有必要复杂化,这也正是本文作者的选择。 好了,言归正传,继续聊回使用pushy实现iOS高性能推送这个话题。 5、APNs和Pushy苹果设备的消息推送是依靠苹果的APNs(Apple Push Notification service)服务的,APNs的官方简介如下:
(如果英文看起来不方便,可以看看《iOS的推送服务APNs详解:设计思路、技术原理及缺陷等》) IOS设备(tvOS、macOS)上的所有消息推送都需要经过APNs,APNs服务确实非常厉害,每天需要推送上百亿的消息,可靠、安全、高效。就算是微信和QQ这种用户级别的即时通讯app在程序没有启动或者后台运行过程中也是需要使用APNs的(当程序启动时,使用自己建立的长连接),只不过腾讯优化了整条从他们服务器到苹果服务器的线路而已,所以觉得推送要快(参考知乎)。 项目组老的苹果推送服务使用的是苹果以前的基于二进制socket的APNs,同时使用的是一个javapns的开源库,这个javapns貌似效果不是很好,在网上也有人有过讨论。javapns现在也停止维护DEPRECATED掉了。作者建议转向基于苹果新APNs服务的库。 苹果新APNs基于HTTP/2,通过连接复用,更加高效,当然还有其它方面的优化和改善,可以参考APNs的一篇介绍,讲解的比较清楚。 再说一下我们使用的Pushy,官方简介如下:
Pushy的文档和说明很全,讨论也很活跃,作者基本有问必答,大部分疑问都可以找到答案,使用难度也不大。 6、在Java端使用Pushy进行APNs消息推送6.1 首先加入包 ![]() 6.2 身份认证 苹果APNs提供了两种认证的方式:基于JWT的身份信息token认证和基于证书的身份认证。Pushy也同样支持这两种认证方式,这里我们使用证书认证方式,关于token认证方式可以查看Pushy的文档。 如何获取苹果APNs身份认证证书可以查考官方文档。 6.3 Pushy使用 ![]() ps:这里的setClientCredentials函数也可以支持传入一个InputStream和证书密码。 同时也可以通过setApnsServer函数来指定是开发环境还是生产环境: ![]() Pushy是基于Netty的,通过ApnsClientBuilder我们可以根据需要来修改ApnsClient的连接数和EventLoopGroups的线程数: ![]() 关于连接数和EventLoopGroup线程数官网有如下的说明,简单来说,不要配置EventLoopGroups的线程数超过APNs连接数:
关于消息的推送,注意一定要使用异步操作,Pushy发送消息会返回一个Netty Future对象,通过它可以拿到消息发送的情况: ![]() APNs服务器可以保证同时发送1500条消息,当超过这个限制时,Pushy会缓存消息,所以我们不必担心异步操作发送的消息过多。 当我们的消息非常多,达到上亿时,我们也得做一些控制,避免缓存过大,内存不足,Pushy给出了使用Semaphore的解决方法:
以上仅是Pushy的基本用法,在我们的生产环境中情况可能会更加复杂,我们可能需要知道什么时候所有推送都完成了,可能需要对推送成功消息进行计数,可能需要防止内存不足,也可能需要对不同的发送结果进行不同处理.... 不多说,上代码(请看下节...)。 7、Pushy的最佳实践参考Pushy的官方最佳实践,我们加入了如下操作:
具体用法参考如下代码:
关于多线程调用client: Pushy ApnsClient是线程安全的,可以使用多线程来调用。 关于创建多个client: 创建多个client是可以加快发送速度的,但是提升并不大,作者建议:
关于APNs响应信息(错误信息): 可以查看APNs官网的error code表格,了解出错情况,及时调整。 8、来看看Pushy的性能作者在Google讨论组中说Pushy推送可以单核单线程达到10k/s-20k/s,如下图所示: ![]() ▲ 作者关于创建多client的建议及Pushy性能描述 但是可能是网络或其他原因,我的测试结果没有这么好,把测试结果贴出来,仅供参考(时间ms)。 ps:由于是测试,没有大量的设备可以用于群发推送测试,所以以往一个设备发送多条推送替代。这里短时间往一个设备发送大量的推送,APNs会报TooManyRequests错误,Too many requests were made consecutively to the same device token。所以会有少量消息无法发出。 ps:这里的推送时间,没有加上client初始化的时间。 ps:消息推送时间与被推消息的大小有关系,这里我在测试时没有控制消息变量(都是我瞎填的,都是很短的消息)所以数据仅供参考。 ![]() 关于Pushy性能优化也可以看看官网作者的建议:Threads, concurrent connections, and performance 大家有测试的数据也可以分享出来一起讨论一下。 ![]() 8、思考和小结苹果APNs一直在更新优化,一直在拥抱新技术(HTTP/2,JWT等),是一个非常了不起的服务。 自己来直接调用APNs服务来达到生成环境要求还是有点困难。Turo给我们提供了一个很好的Java库:Pushy。Pushy还有一些其他的功能与用法(Metrics、proxy、Logging...),总体来说还是非常不错的。 同时感觉我们使用Pushy还可以调优... 下一页:找不到相关信息
说点什么
发表
最新评论
|
点击开启全网营销