推送,从入门到放弃

推送

推送简直就是一种轻量级的骚扰方式

自从有了推送,各个公司基本上都在使用推送,这确实是一个比较好的提醒方式,Android较iOS强的一个部分,也就是在于Android的Notification。Google教育我们利用好Android的通知模块,做更多友好的交互,可这句话,翻译成中文,不知不觉,就变成了在Notification中推送各种广告,而且仅仅就是一些广告,Notification各种牛逼的功能,完全不需要,这也违背了Google设计Notification的初衷。

更关键的是,现在随便找一款App,没有推送的真是凤毛麟角,更可恶的是,做外卖的App给我推送奥运新闻,一条新闻十几个App推送,以至于现在很多用户都非常反感各种推送广告,就我本人而言,基本上会禁用所有广告类的App的推送。

本人非常反感推送,借用王思聪的一句话,XXX App天天给我推送各种广告,还TM是自己做的推送,真是绝了。

推送方案

轮询

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

SMS

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

长连接

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

推送方案

iOS

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

GCM

与iOS一样,Android同样有一套内置的推送方案,但很可惜的是,Google的服务在中国大陆无法使用,草了个蛋。

第三方推送服务

专业的第三方推送

  • 极光
  • 个推
  • 友盟推送

手机ROM厂商推送

  • 华为推送
  • 小米推送

BAT级别的全家桶

  • 阿里推送
  • 信鸽推送
  • 百度推送

关于第三方推送服务在各个App中的使用率,大家可以参考贾吉鑫的那篇文章,微信没办法贴链接。。。麻烦大家自己搜一下。

第三方推送注意

这些推送服务大同小异,基本上一家使用了一个新功能,另外几家,也会很快推出这个功能,就例如之前比较火的,『共享推送通道进行App唤醒』这个技术,友盟、个推推出后,很快其它推送服务商就支持了,所以开发者并不需要担心哪一家推送功能比较强。

这里还需要说下现在的『推送唤醒』这样一个功能,简单的说,就是所有安装了A推送的App,只要有一个还活着,就可以把其它安装了A推送的App拉起来,从而提高推送的到达率。有些阿里系、百度系的App,被大家称作『全家桶』,实际上就是因为这个原因,这个方式,确实能在一定程度上提高推送到达率,但另一方面,也破坏了Android生态,增加了功耗,打乱了系统的清理策略。

另外,小米推送、华为推送,大家接入的原因可能很简单,就是他们的手机市场占有率比较高,接入他们自家的推送,可以在一定程度上提高到达率,但需要注意的是,推送分为透传和非透传两种方式,透传即我们自己App处理推送消息,而非透传,则是交给相应的PushSDK处理,对于小米推送、华为推送来说,只有采用非透传消息,到达率采用保证,而透传消息,与其它推送并没有什么区别,换句话说,小米手机、华为手机,只对非透传的推送消息做了可靠性保证,但非透传消息的展示格式非常固定、简单,且不能自定义,这是一个很大的问题,这点应该是很多开发者的误区。

最后,很多推送服务都需要在Application中进行初始化,同时,各种被唤醒策略,又会拉起Application,导致推送进程的重复,所以,这里经常需要对进程名进行过滤,非主进程,不进行初始化。

自建推送服务

基本都是基于AndroidPN、MQTT、XMPP、长连接这些方式去实现的,自己搭建Push平台服务,一个最大的问题就是服务端的架构设计,不仅成本高,而且效果不一定好,建议中小企业不要轻易尝试。

推送名词解释

RegistrationID\ClientID

一般来说,类似这类ID都是用于唯一标识应用\用户的,每个App在每台手机上都会生成一个唯一ID。

RegistrationID\ClientID生成规则

Android平台上因为国内存在大量山寨设备,所以很多设备的IMEI、Mac地址、AndroidID 都有可能为空或者错误,所以不能单独作为唯一标识,需要将这些进行组合起来使用。

对于应用卸载后RegistrationID的问题,很多PushSDK的策略是,生成一个DeviceID保存到本地存储,应用被卸载后如果被重新安装,如果检测到存储里的DeviceID还在的话,就判定是同一个设备,不重新生成RegistrationID。

AppKey\AppID

这些Key基本都是用于验证App的,每个包名对应一个加密的Key。

透传\非透传

非透传消息是指推送消息被PushSDK获取并处理,透传消息是指推送消息被PushSDK交给宿主应用处理,非透传消息通常只能设置一些固定的样式,比较简单,而透传消息,可以由App自定义处理,比较灵活。

推送数据基础

累计注册

通过应用使用的appid统计用户注册总量。

日在线用户

通过应用使用的appid统计当天的在线用户数。

活跃用户

通过应用使用的appid统计当天在推送平台激活过的用户总数。

在线下发率

在线消息下发数/总下发数。

回执率

消息回执数(去重)/消息在线下发数。

到达率

到达数/实际下发数。

百日内联网用户数(可推送用户数)

是指最近三个月内有登录过(设备与推送服务端建立长链接)的设备总数,即有效可下发的用户数。一般的推送服务端认为,设备在100天内没有登录请求,认为该设备已经失效,所以无需再次发送。

实际下发数

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

到达数

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

展示数

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

点击数

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

推送数据分析

那么关于推送,大家实际上最关系的,就是『到达率』。那么这个到达率究竟怎么计算呢?

首先我们举个例子来说明上面的这些数据背后的实际意义,例如,我们有一款App,有100w的下载量,每个App启动后,都将上报给服务器一个唯一ID,所以,累计注册量就是100w,也称发送总量。

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

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

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

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

而且,这个到达率与iOS完全没有可比性,因为iOS统一通过APNs来进行推送,且无法获取到达回执,所以,iOS基本不存在到达率这一说法,如果有,几乎也是100%,完全没有意义,所以,如果哪一天有产品或者运营跟你说,为什么Android的到达率比iOS的到达率差这么多,请毫不客气的砸它一斤苹果。

Tag\Alias

Tag

Tag,或者叫标签,是用户的一种属性,在给某些用户设置某类标签后就可以针对推送。比如给喜欢『编程』的人打上『编程』的标签,就可以只给他们精准推送。

通常情况下,一个设备(在一个App里)可以设置多个标签。标签与别名类似,其对应关系也是保存在推送服务器侧的。

Alias

Alias,或者叫别名,是对已经安装某应用的用户取个别名进行标识,在对该用户消息推送时,就可以用此别名来进行推送。设置了别名后,推送时服务器端指定别名即可。推送服务器端来把别名转化到设备ID来找到设备。

Tag和Alias他们的共同点在于,提供对用户的精确推送。

推送原理

目前大部分的第三方推送服务,都是基于长连接的推送方案,下面将对这个方式进行详细讲解。

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连接。

心跳包谁来发

既然需要定时任务,那么就需要使用AlarmManager来作定时唤醒了,原因我之前的文章有讲过,是关于处理器唤醒的原因,这里就不赘述了,大家可以参考我之前的文章:

Android中的睡与不睡

进程保活

所谓进程保活,是指App希望尽可能的保证自己的App的推送进程能够存活在后台,以保证可以收到服务端的推送消息,因此,才出现了一大批关于进程保活的方式,例如NDK层的文件锁,fork子进程、前台服务、进程优先级等等方式,然而,这些东西,实际上,都不能完全保证手机的进程管理策略放过你,特别是Android 5.0以后的系统,Android对进程的管理更加严格,还有国内的这些ROM层的修改,ROM想要杀你这个进程,你怎么做也没有办法,哦,除了白名单。所以,不要再花心思去找什么进程保活的黑科技了,好好做好应用,提供用户的使用黏性,才是最佳的保活,而对于一些产品、运营所谓的『为什么微信、QQ都可以保活』这样的问题,我建议你回答它:『如果你能把产品做到微信、QQ那样的数量级,我也能让你活!』

推送整合方案

介于各种第三方推送与ROM推送的特点,我们目前采用的推送方案,名为『UniversalPushSDK』,即整合了多个不同的推送渠道,通过模板设计模式来进行整合,并向外暴露统一的接口,这种方式的好处在于UniversalPushSDK利用的各个不同推送特点,提高推送到达率,但是坏处在于,包的体积会大一些。例如,我们现在整合了『小米推送、极光推送、华为推送』,在系统启动的时候,判断当前系统,如果是小米系统,则启用『小米推送』,如果是华为手机,则启用『华为推送』,其它的Android设备,则启用『极光推送』,通过这种方式来设计我们自己的推送SDK,可以在一定程度上,利用好各个推送平台的特性。

那么如果利用这种方式来设计SDK给到不同的App接入,就需要能够将应用的推送Key做到动态配置,这也是我们遇到的最大的一个问题,解决方法大家可以参考我之前写的一篇文章:

http://blog.csdn.net/eclipsexys/article/details/51283232

虽然我极力反对这种方案,我坚持认为,做好App,提升用户使用黏性,才是提升推送到达率的关键

原文发布于微信公众号 - Android群英传(android_heroes)

原文发表时间:2016-09-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏WeTest质量开放平台团队的专栏

浅谈服务器性能测试的全生命周期——从测试、结果分析到优化策略

服务器性能测试是一项非常重要而且必要的工作,本文是作者Micheal在对服务器进行性能测试的过程中不断摸索出来的一些实用策略,通过定位问题,分析原因以及解决问题...

32040
来自专栏java思维导图

一篇文章弄懂CDN技术原理

概述 Internet的高速发展,给人们的工作和生活带来了极大的便利,对Internet的服务品质和访问速度要求越来越高,虽然带宽不断增加,用户数量也在不断增加...

66830
来自专栏SAP最佳业务实践

SAP最佳业务实践:ETO–报价处理(232)-6项目计划

CJ2B项目计划 已经使用模板(包含进一步处理所需的全部设置)创建项目。现在,必须根据询价中的需求进行计划。同时,还有些调整也必须在此完成,即更改缺省工作,为活...

35150
来自专栏携程技术中心

携程2015 Open House获奖项目:火车票订单中心重构

给绿皮车换上高铁发动机 火车票订单中心重构 web订单系统,对我们来说,都不是一个陌生的东西。然而,高并发从技术的角度来说,这对于Web系统是一个巨大的考验。当...

23080
来自专栏微信小程序开发

开发小程序被问到最频繁的问题(下)

连胜老师在自己的微信小程序开发群里,也经常帮人解答问题,在这里整理一下最频繁被问到的小程序问题。本篇是《开发小程序被问到最频繁的问题(上)》的续篇。 9、用户不...

1.2K90
来自专栏FreeBuf

信息收集利器:ZoomEye

? 前言 ZoomEye是一款针对网络空间的搜索引擎,收录了互联网空间中的设备、网站及其使用的服务或组件等信息。 ZoomEye 拥有两大探测引擎:Xmap ...

41480

32位 or 64位:Apache CloudStack系统VM架构选择

最近我和一些朋友讨论了一个关于CloudStack的问题:为什么现在CloudStack 4.3同时提供32位或64位系统虚拟机的选项。我提出了一个观点,并将其...

23160
来自专栏java一日一条

Linux 新手容易犯的 7 个错误

改变操作系统对于任何人来说都是迈出的一大步,特别是当许多用户不确定操作系统究竟如何的时候,尤其如此。

15410
来自专栏云计算D1net

让云API远离黑客攻击

没有合适的安全措施,云API就会成为黑客的一扇门。那么如何确保云API的安全呢? 开发者可以使用云应用编程接口编码,而这个接口具备一项云提供商的服务。但是同时对...

42160
来自专栏散尽浮华

网站系统架构梳理-解决高负载高并发

随着互联网业务的不断丰富,网站系统架构已经细分到方方面面,尤其对于大型网站来说,所采用的技术更是涉及面非常广,从硬件到软件、编程语言、数据库、WebServer...

497110

扫码关注云+社区

领取腾讯云代金券