JB的测试之旅-消息推送功能了解下

1,212 阅读16分钟

前言

昨天参加个需求评审,产品经理说下个版本要接入推送功能,啪啪啪的说了一堆想要的效果,最后来了一句,我觉得腾讯的信鸽蛮好的,没啥意见就接入这个吧;此时,产品负责人说,用极光吧,信鸽这种听都没听过;

第一个感觉是,好像很随便,接入这种东西,没有一个准则?
之前在上家公司,是内部做的push功能,后来接入了小米、魅族推送,虽然不是我负责测试,但是也知道这玩意水深,国内的推送环境非常的乱,因此,本篇就来介绍下第三方推动的内容,便于快速上手了解;

推送介绍

概念及相关知识

推送通知就是向用户推送一条信息来通知用户某件事件,可以在应用退到后台后,或者
关闭后,能够通过推送一条消息通知用户某件事情,比如版本更新,QQ来消息等等。

这种就是了~

消息推送的分类

1)本地推送通知:
不需要联网,在代码钟推送的通知,确定知道某个时间点应该推送什么;

2)远程推送通知:
需要联网,由服务端推送发起的通知,不确定时间,因此app手机要有一个推送进程来接收消息;

安卓跟IOS推送介绍

iOS

ios系统的推送(APNS,即 Apple Push Notification Service),依托一个或几个系统常驻进程运作,是全局的(接管所有应用的消息推送),是设备和苹果服务器之间的通讯;

例子:
腾讯QQ的服务器会向苹果公司对应的服务器(APNs)发出通知,然后再中转传送到你的设备上;
当你接收到通知,打开应用,才开始从腾讯服务器上后去数据,这个过程是经由2个不同的通道而来的;

ios的推送可以简单的理解:
APNs朝手机后台挂的一个IM服务程序发送消息,然后系统根据该IM消息识别告诉哪个APP具体发生了什么事,再分别通知这些APP;

优点:

  • 安全
    只有登录过的开发者才可以通过苹果的服务器推送;
  • 稳定,可靠
    苹果掌控推送服务器;
  • 性能更好
    因为苹果不允许应用在后台活动,体验更好;

原理图

可以分为5步:
1)应用程序注册消息推送;
2)IOS跟push server要device token,应用程序接受device token;
3)应用程序将device token发送给push服务端程序;
4)服务端程序向APNS服务发送消息;
5)APNS服务将消息发送给iPhone应用程序;

安卓

安卓的推送,每个需要后台推送的应用有各自独立的后台进程,才能和各自的服务器通讯,交互数据;

当然,安卓也有类似APNS的GCM(Google Cloud Message),但是因为需要Google框架,所以基本不会选择,国情你们都懂的;

而APP挂后台是安卓的一个特性,所以推送进程挂后台登录就成为大家的选择了;

其实APNS跟GCM的技术实现原理是类似的:
在系统层有一个常驻的TCP长连接,即时手机休眠的时候也在保持着长连接
那会不会有耗电问题?这要看长连接的心跳时间,只要不是太频繁,理论上不会存在性能问题;

推送的方案

轮训

轮询是最简单的与服务器保持通信的方式,即循环向服务器通信。
这个方案的特点就是通信由客户端主动发起,你需要自己实现轮询消息队列、频率等等参数,在功耗和效果间做权衡,类似于TCP的短连接。

SMS

这个其实就是借助短信来实现信息的展示,只不过把短信内容展示到了Notification中,这个方案,到达率确实高,毕竟短信是比较可靠、稳定的,但劣势也很明显,就是成本很高,而且在Android平台上,短信的权限比较开放,容易被劫持。

长连接

长连接的短连接,都是基于Socket连接的方式;
它们的区别在与,短连接是每次数据传输完毕后就断开连接,而长连接不会。
所以,基于轮询的方式,每次都要进行链路的连接,性能消耗更大,基于长连接的方式,就是对这点的改进。
应用一旦与服务器连接成功,并不会主动断开连接,后面的通信都基于这个通道。
目前大部分的推送服务都是基于长连接的推送,在后台维护一个Service,维持应用与服务端之间的TCP长连接。

ios推送

如上所说,iOS这边使用系统统一的APNs,所有推送消息都由苹果的服务器进行下发,同时,也由系统进行统一展示和处理。

GCM

与ios一样,是android内置的推送方案,但是因为Google服务不能在大陆使用,gg了;

第三方推送服务

第三方推送平台又可以分3类,如下:

这里介绍下推动服务的特征:
系统级别推送-手机厂商

  • 特征:系统级长连接,实现方式类似于IOS 平台 APNS。
  • 厂商:有能力控制上游ROM的厂商,在系统中内置自己的推送服务通道,如 Google GCM、小米推送、华为推送 等
  • 优点:使用系统服务,省电,可靠,成功率高,app被完全杀死后仍能收到推送。
  • 缺点:Android 平台碎片化问题,各家的服务通道不能通用,GCM 只能在有完整Google 服务框架的手机上使用,其他类似。

三方推送

  • 特征:app级长连接通道。
    标配:由系统事件广播保活进程。
    pro:独立进程,共用长连接,链式唤醒等。
  • 厂商:提供推送及增值服务,如友盟推送、个推、腾讯信鸽、百度云推送等
  • 优点:通用性较强,各种ROM上都能用,app在活动时成功率与系统级推送相当。
  • 缺点:app被杀死后成功率较低,这点在国产ROM上尤为明显。
    进程保活、链式唤醒会导致耗电量增加。
    进程保活和唤醒机制受限于系统及各种优化软件。

划重点:
这也意味着,在MIUI系统上接入小米推送,系统是不会kill掉小米的推送服务的!

混合推送

  • 特征:同时包含系统级长连接通道和 app 级长连接通道
  • 厂商:小米推送,阿里云推送,LeanCloud Push,极光推送等。
  • 优点:适应性比纯系统级推送强,成功率相对纯三方推送较高
  • 缺点:除小米推送外,其他推送方式都是以胶水的方式捆绑了系统级推送和自家三方推送(类似于友盟分享),开发成本相对稍高。

接入小小结

1)手机厂商的推送服务在自家的手机上属于系统级别的服务,这意味着系统不会杀死自家的推送服务!!!
这也意味着,在MIUI系统上接入小米推送,系统是不会kill掉小米的推送服务的!

2)三方平台类会共享一条推送渠道,达到保活和互拉的效果,这也是他们的优势;
比如:你的App跟今日头条用的是同一个推送,比如极光;
你的App被杀死了,但这时用户启动了今日头条,那么推送系统也就会通过共享的推送通道顺便把你推送消息送达到手机上,然后还可能把你的进程也唤醒;
3)BAT的推送暂时没发现有特别优势,不会说用了信鸽,微信就会拉起我们的app;
4)如果希望进一步提高推送的效果,其实可以集成多个手机厂商的推送服务,
比如小米渠道用小米推送,华为渠道用华为推送,但这样的实现成本会大一些;

UC除了用阿里云的推送,还接入了小米、魅族,就是为了提供推送的效果

推送消息类型的选择

类别

一般第三方推送平台都支持两种推送消息类型:通知栏消息和透传消息

  • 通知栏消息,该类消息在被送达用户设备后,直接以通知栏的形式展示给用户
  • 透传消息,该类消息被送达用户设备后,还会继续传递给app
    通过回调App的某个BroadcastReceiver的形式将消息传递到App内部。然后由App决定如何处理和显示这个消息。

那二者的区别就在于,透传消息在整个消息传递过程中比通知栏消息多了一步--传递到APP;

特点

通知栏消息的优点:送达率高;
因为透传消息在整个消息传递过程中比通知栏消息多了传递到APP这么一步,就会增加被系统限制的概率,从而提高被系统kill掉的概率;

比如安卓手机的系统设置有限制,应用不能在后台自启动,这种情况下发送消息,透传类消息肯定是送不到的!

透传消息的优点:自定义程度高
通知栏消息用的样式都是默认的,使用透传后,就能自定义提示样式;
并且app自身能接受到数据,拿来统计分析之类的,大数据时代嘛,数据为重;

根本区别在于,通知消息走的是系统公用通道,透传消息走的是app私有通道;

端内

通常大厂app的做法是,区分端内跟端外推送,这里的端是指app客户端,具体是这样的:
1)当App在前台运行的时候,这时的推送称为端内推送。
端内推送一般是走App自己实现的一套推送系统:推送服务器是自己的,客户端维护一条长连接连到自己的推送服务器,不依赖任何第三方的推送系统。

2)当App从前台退到后台,在短时间内App未被杀死前,App自己的长连接仍然有效。
这时的推送可以仍然走App自己的推送系统。所谓的“Android进程保活”,就是为了尽量延长这段在后台存活的时间。

3)当App在后台运行足够长的时间后,App进程由于被清理或者其它原因,App自己的长连接断开。
这时的推送就称为端外推送了,只能走某个第三方推送平台了。

所以大厂的推送策略基本是,优先使用自己的推送,不行再走第三方的推送平台,因为自己的推送更快;
假如第三方的服务器挂了或者有BUG,怎么办?
假如用户手机上的app都集成一个第三方,然后同时一起推送,这里面就存在推送延迟的可能性,比如一些新闻类的app,拼的就是谁推送的快,不然无论前面运营多块,结果push卡住了,就尴尬了;

而且端内的实现成本很高,如何保活,如何数据不丢失,高并发,长连接状态、安全性等等,所以端内推送,一般是大厂或者有一定规模的app才会用的,对于小公司而已,最直接就是走端外;

推送的指标

实际下发数

实际可推送设备数(在消息有效期内,有联网并推送进程正常的设备,即消息有效期内的在线下发数。消息有效期就是设置的离线时间)。

到达数

客户端SDK接收到消息的设备数(通过统计客户端SDK接收到消息后的回执获得)。

展示数

用自定义非透传消息在用户手机展示过的设备数。

点击数

点击通知栏消息的设备数。

指标说明

下面以一个例子来介说明下到达率怎么算,并且把上面提及到的数据介绍下;

例如,我们有一款App,有100w的下载量,每个App启动后,都将上报给服务器一个唯一ID;
所以,累计注册量就是100w,也称发送总量

那么在服务端准备发送推送的时候,当前手机端推送进程还活着的,也就是说推送的长连接还健在的,就是在线设备,如果按天算,那么就叫日在线设备数,我们假设这个数字是60w。

OK,推送发出去后,客户端收到推送消息,并产生回执,代表完成了一次推送,假设这些完成推送的设备是55w,这个就是送达设备数
一般来说,只要设备在线,基本都能送达,所以这个数字和在线设备数非常接近,不接近的话,这个推送基本就有问题了,其中可能送不达的原因就在于网络切换等导致长连接断掉这类因素。

那么到这里,一般的推送服务商会使用送达设备数/在线设备数的方式来计算到达率,当然,前面我们也说了,这个比例一定是很高的,如果保持长连接的设备都不能收到推送,那一定是有问题了。

而一般的到达率,应该是送达设备数/可送达设备数,也就是百日内活跃的设备数,这样一除,这个比例一下子就小了很多,因为谁也不知道,这一百天内曾经活跃的用户,第二天是不是就已经把你卸载了。所以说,Android下统计推送的到达率一般都很低,而推送服务商宣传的到达率都很高,这其实就是一个偷换概念的问题,我们说的是一般的到达率,而服务商宣传的是在线到达率。

而且,这个安卓的到达率跟IOS没有任何关系,因为ios是通过APNS推送的,不存在到达率的说法,如果有,那就是100%;

推送原理

因为目前大部分的第三方推送是基于长连接的推送方案,因此就对这个方式进行讲解;

NAT

网络基本知识——NAT,即网络地址转换(Network Address Translation,NAT),这是因为IP地址是有限的,手机无论是通过路由器还是数据网络,都有一个内网IP地址,同时,路由器上会维护一个外网IP地址,从而形成一个NAT路由表,即内网IP地址:端口,以及对应的外网IP地址:端口。这样通过一层层封装与解封装,就达到了内网与外网交换通信的方式。

NAT超时

由于NAT路由表的大小有效,所以一般路由都有NAT有效期,WIFI下,这个NAT有效期可能会比较长,而在数据流量下,运营商一般都会尽快更新NAT路由表,淘汰无效的设备,所以,在使用数据流量时,长连接经常容易断。

那么除了NAT路由表主动淘汰过期的设备之外,切换网络环境和DHCP服务器租期到期,这些情况都有可能导致NAT路由表改变,从而造成长连接中断。

心跳包

现在的推送服务一般采用的是长连接的通信方式,而长连接会因为NAT路由表的更新而中断,所以,客户端会定时向服务端发送一个心跳包,来定期告知NAT路由表,我还活着,别杀我!
这就是心跳包的作用——防止NAT路由表超时,同时检测连接是否被断开。

心跳包的心跳时间

既然心跳包的作用是防止NAT超时,那么就需要将心跳包的发送频率设置为小余NAT超时的检测频率,而WIFI和数据流量下,对于NAT路由表的超时时间又是不一样的,而且不同的网络运营商的超时时间,甚至都不一样,所以,一个比较好的方法就是根据设备当前网络环境,来动态的设置心跳时间。

注意,心跳包与轮询是不一样的,心跳包建立在长连接上,只要发送数据即可,而轮询每次都是一个完整的TCP连接。

心跳包谁来发

在长连接的情况下,建议两边都要发,或者其中一边是被动方式,如果一段时间内收不到心跳包就直接断开连接;

当然,站在节约服务器资源的角度,大部分都是让客户端发,不过这块没有具体的规定,不同场景有不同的定义~

测试点

既然推送那么坑,那测试的时候需要注意啥?那可多了。。
主要是进程保活,通道能力,各类开关(系统权限和用户手动),样式和消息在各机型的兼容性适配,性能消耗(服务端,APP端、流量、电量)、sdk接入的size。。。

上面的东西,一展开一大堆。。。

小结

本文算是对消息推送的功能简单介绍了,不涉及原理,不涉及代码,适合小白用户~

Ios只能适用苹果的APNS系统推送服务,生态稳定;
安卓是每个应用需要有各自独立的后台进程,才能跟各自服务器通讯,而安卓自带的GCM应进不来市场,无法适用,导致国内安卓推送百花缭乱;

第三方推送分为厂商、第三方平台、BAT;
厂商的话,建议优先考虑小米推送,因为小米推送在MIUI上属于系统推送,极少被干掉的可能;
而且市面上MIUI占比可观,因此优先建议小米推送;

第三方平台可以考虑极光跟个推,身边朋友好像都用极光比较多,但是没有详细数据,借鉴就好了;

谢谢大家~