百亿级日志流分析实践 | 剖析个推 SDK 后效分析功能实现原理
消息推送作为用户促活的有效利器,具有低成本、高效率的明显优势,已成为 App 运营中最重要的用户触达方式之一。为帮助开发者有策略地提升 消息推送的效果,增加消息的到达率和点击率,个推消息推送 SDK 于今年初重磅上线了后效分析功能,旨在为开发者和运营人员科学调整推送策略提供有效支撑。
后效分析功能上线后,我们结合产品目标和用户建议,进行了多次迭代。本文就开发和迭代过程中沉淀的经验与大家做分享,也欢迎感兴趣的开发者们和我们交流。
后效分析功能的开发背景
消息推送过程中,从服务端推送消息、消息到达客户端,到用户点击推送、打开应用的各阶段,都可能存在消息折损的情况。
以往,消息系统通过简单对比下发、到达、展示、点击等四个维度的数据,来计算消息的折损程度。但这样的消息折损计算方式不够准确,运营人员较难深入了解消息的折损原因,也就无法对推送参数、推送设置做出科学有效的改进。此外,以往客户遇到消息推送的问题时,会直接与技术支持人员联系解决,沟通和时间成本较高。
因此,我们需要设计出一种自动化方式,来帮助开发者清晰了解推送消息的各项后效数据,并能够自主、高效地找出消息折损的原因。
后效分析功能的开发思路
我们的解决思路是:
1.推出后效数据报表功能。通过将消息在服务端下发过程中的折损情况以及客户端回执数据进行梳理、统计,形成各环节后效数据的清晰报表,以帮助开发者和运营人员透过数据表象,快速定位出消息折损原因,找到提升推送效果的关键环节。
2.自动采集各推送模块日志并形成后效分析报告。通过不同模块获取推送日志:以类似人工查询日志的方式,将一些含有原因标识的日志进行统一存储和梳理,从而梳理出某条任务下发时产生的所有异常和折损原因。这其中就包含“目标正处于黑名单”“请求受到频控(或流控)限制”等原因。与人工技术支持相比,这样不仅能提高后效分析的效率,还能从一些以往可能被忽略的折损中自动提炼出问题,帮助用户自检并规避一些使用不当的情况。
后效分析功能的开发难点
在开发后效分析功能的过程中,我们也遇到了如下一些技术上的难点:
难点一
日志的聚合归类和后效原因提炼
在通过日志进行消息折损原因排查和分析的过程中,我们首先需要从海量日志数据中筛选出有效的部分,并对该部分日志数据进行归纳,根据我们预先设置的日志解析策略,对全链路的日志数据打上对应标记,以帮助我们分析消息在各阶段的折损原因。
为此,我们对消息推送的整个链路做了一次大梳理,从推送阶段入手,将推送模块区分为入口层、处理层、下发层、客户端等四层,然后对各层可能存在的消息折损原因进行了提炼:
✦在入口层,我们主要关注服务端收到的请求内容是否通过格式校验,以及各类目标参数是否设置无误,比如“CID 是否有效”“鉴权信息是否异常”等。
✦在处理层,我们关注目标客户端是否符合下发条件,例如可能因为推送策略限制,导致服务端无法给部分客户端进行后续推送。
✦在下发层,我们关注客户端与服务端的网络连接是否正常,比如,在线通道是否有效等。
✦最终在客户端收到推送、用户点击消息时,客户端也会将回执汇报到服务端模块。这一阶段的消息折损原因可能是“通知开关没有打开”等。
基于以上业务层次区分,我们可以更清晰地看到消息推送的整体业务流程。我们将各阶段可能存在的异常关注点提炼出来,以便于我们梳理相对应的日志模块。最终我们将后效异常原因总结为 1 2 类,分别对应消息推送各阶段中可能遇到的折损情况。
难点二
TB 级别日志数据的处理和准确计算
基于上述各场景,我们筛选出相关日志,通过前期的标记来提炼消息折损原因。
在一条消息的下发过程中,服务端会产生大量日志,单个功能节点一天的日志量就能达到 TB 级别。如何对亿级别的日志进行过滤和计算,成为我们进行后效数据分析的第一个难题。
我们通过 Flume 传输日志,将日志数据写入到 HDFS,采用 Spark 作为计算引擎,HDFS 存储原始日志数据和维度数据,最后的报表数据存放在 ElasticSearch、Hbase 和 Mysql 中。
海量日志数据的清洗和计算
根据对推送业务特性的了解,我们总结出推送日志数据可能存在的问题如下:
✦ 日志重复。例如,用户不断地登录和登出服务,从而产生大量的重复日志。
✦ 请求重复。例如,用户多次发起相同请求,对某个客户端发送同一条消息。客户端最终只会收到一次消息并展示,但服务器会产生多条重复的客户端/消息关联日志。
✦ 回执重复。下游回执中,由于客户端的网络环境复杂,有时会出现重复回执的情况,从而导致服务器重复打印回执日志。
✦ 日志不足。比如,一般情况下,关闭通知、设备活跃等客户端信息,在推送流程中不会有日志产生,这就必须依赖相关数据作为补充,才能综合评估出客户端的状态信息。
针对以上问题,我们提出的解决办法是“人群打标”。我们按照推送流程对日志数据进行划分,将推送任务影响到的人群分为到达人群、下发人群、请求人群等三类。我们根据消息与客户端的关联情况,对客户端进行打标。例如当采集到“在线下发模块”日志时,如果其中包含某消息与客户端的关联信息,那么我们就会给该推送任务下的客户端打上成功下发标记。每个标记只有 0 或 1,不同日志不会重复打标,如此就避免了日志重复统计的情况。
结合上述人群打标逻辑,我们将四个维度的打标数据汇总,最终得到单个推送任务的原始数据。这份数据内,一个客户端会有多个标记,我们只需要按过滤逻辑将这些标记整理并归纳出最终状态,就可区分该条消息对这个客户端的下发流程最终到了哪一阶段,或是在哪一阶段因何种原因折损。
解决数据倾斜问题
在日志数据的计算过程中,我们还遇到了数据倾斜的问题。
我们按照消息下发阶段将整个日志计算任务拆分成四个。根据推送漏斗,这四个任务之间存在上下游关系。在对指标维度进行聚合的时候,会出现维度聚合体量差异过大导致数据倾斜的情况,甚至因为个别任务计算时间过久拖慢整体的计算进度。
为了解决该问题,我们需要在计算前和计算时对 Spark 任务进行处理,以减少数据倾斜。
我们采取的处理方式有:1.将大文件分割成小文件,或将小文件合并成大文件,以此保证每个任务处理的日志数据量均匀;2.优化分区策略,防止某个较大推送请求下的所有数据全部汇聚到同一节点,使节点计算压力更均衡;3.优化任务的计算链路,保证以最优的计算链路完成数据处理。
至此,基于如上所述的日志数据处理和计算逻辑,我们就可以在 HBase 中存储每条任务的后效数据,从而供业务层查询、调用。
总结
近期,我们还引入了 Flink 流式计算引擎来提升后效数据计算的实时性;我们也结合了更多的消息细则日志进一步完善数据,将后效数据报表升级,推出了消息链路查询功能,借此来帮助开发者更好地了解推送消息下发情况,并根据对应建议来快速提升消息的整体到达率。
“码”上注册和登录个推开发者中心(https://dev.getui.com/),体验个推后效分析功能和最新推出的消息链路查询功能吧!
评论