背景
结合《蚂蚁金服面对亿级并发场景的组件体系设计》,我们能够通盘了解支付宝移动端基础组件体系的构建之路和背后的思考,本文基于服务端组建体系的大背景下,着重探讨“自动化日志手机与分析”在支付宝 App 内的演进之路。
支付宝移动端技术服务框架
这是整个支付宝移动端无线基础团队的技术架构图,同时蚂蚁金服体系内的其他业务 口碑、网商银行、香港支付宝、天弘基金等) 通过移动开发平台 mPaaS进行代码开发、打包、灰度发布、上线、问题修复、运营、分析。因此,mPaaS 源自于支付宝移动端的核心技术架构,并在 App 全生命周期的每个环节提供特定的能力支持。接下来,我们将着重分享“日志诊断”和“移动分析”两个能力背后的架构演进和选型思考。
支付宝移动端技术服务框架:数据分析框架
如图所示,即数据分析能力的技术架构图,其中“数据同步”、“埋点SDK”、“日志网关”是移动端专属的能力,其余部分是所有的数据分析平台都必须具备的数据结构。
1. 日志采集
接下来我们重点分析支付宝移动端的日志采集框架,首先第一部分是“日志 SDK”,日志 SDK 会向业务层提供一个埋点接口,使用起来就和 Java 里面的 logger.info 的感觉一样:业务层只需要把想记录的信息传递给日志 SDK。日志 SDK 会在拿到业务日志后,去系统内部获取相关的系统级别的上下文信息,比如机型、操作系统版本、App 版本、手机分辨率、用户ID (如果用户登录了)、设备ID、上一个页面、当前页面等,接着把这些信息与业务日志内容整合成一个埋点,然后记录到设备的硬盘上。对,只是记录到硬盘上,并没有上报到服务端。
日志 SDK 会在合适的时机,去和日志网关交互,判断获取什么样的日志、什么级别的日志可以上报。如果可以上报,是以什么频率上报、在什么网络条件下上报。因此通过日志 SDK 与日志网关的交付,我们可以来实现日志的策略式降级。日志的策略式降级这点对于支付宝特别重要,因为目前支付宝的体量,日常的日志上报量为约 30W 条日志/s;而在大促的时候,日志量会是日常的几十倍! 所以,如果大促期间不采用任何的日志降级策略的话,我们的带宽会被日志打包,支付宝的正常业务功能就不可用了。
由此,我们可以总结,在大促高并发场景下,我们需要只保留关键日志的上传,其余日志统统降级。即使是日常业务处理,我们也只允许日志在 WIFI 条件下上报,防止发生流量相关的投诉。
埋点网关除了提供日志上报的策略开关能力之外,就是接收客户端的日志。它在接受到客户端日志之后,会对日志内容进行校验,发现无效的日志会丢弃掉。而对有效合法的埋点,会根据客户端上报的公网 IP 地址,反解出城市级别的地址位置信息并添加到埋点中,然后将埋点存放在它自己的硬盘上。
2. 埋点分类
经过多年的实践,支付宝把日志埋点分为了四类。
(1)行为埋点:用于监控业务行为,即业务层传递的日志埋点属于行为埋点,行为埋点属于“手动埋点”,需要业务层开发同学自己开发。不过也不是全部的业务行为都需要业务方手动开发,有一些具备非常通用性的业务事件,支付宝把它们的埋点记录放到了框架层,如报活事件、登录事件。因此,行为埋点也可以叫做 "半自动埋点"。
(2)自动化埋点:属于“全自动化埋点”,用于记录一些通用的页面级别、组件级别的行为,比如页面打开、页面关闭、页面耗时、组件点击等。
(3)性能埋点:属于“全自动化埋点”,用于记录 App 的电量使用情况、流量使用、内存使用、启动速度等。
(4)异常埋点:属于“全自动化埋点”,严格上讲,也算是性能埋点的一种。但是它记录的是最关键的最直接影响用户的性能指标,比如 App 的闪退情况、卡死、卡顿情况等。这类埋点,就属于即时大促期间也不能降级的埋点!
图中的代码示例即为一条行为埋点样例,大家可以看到,埋点实际上就是一条 CSV 文本。我们可以看到里面有日志网关添加进行的地址位置信息内容,也有日志 SDK 给添加的客户端设备信息。
3. 日志处理模型
下面我们来整体了解支付宝内部日志处理的通用流程:
(1)日志切分
我们已经了解到,埋点实际上即为一段 CSV 文本。而所谓日志切分呢,即将 CSV 格式的文本转成 KV,通俗点说就是内存里面的 HASHMAP。这个切分的过程,可以直接根据逗号进行切换,当然也还有很多其他的办法。
(2)日志切换
日志埋点中的内容,并不是直接可以拿来进行分析的。比如客户端启动时间,相关数据是按照毫秒级别的颗粒度进行上报,但实际应用上我们只需要把数据分析到某个特定区间内的个数,所以在处理之前一般会做一个具体启动时间到截止时间范围编码的映射。除了这种转换之外,还会有一些白名单、黑名单之类的过滤转换。
(3)维表影射
因为客户端并不能拿到业务方需要分析的所有数据维度,如用户的性别、职业等内容,因此在真实分析之前,我们可以通过维表映射,将日志埋点中的用户 ID 映射成业务层面的具体属性来进行后续的分析。
(4)UID 的滤重
UID 滤重的指标有两种:一种是 PV 指标,一种是 UV 指标。
UV 指标在做具体的计算之前,要做一步 UID 去重。所谓 UID 去重就是指检查这个 ID 在一定时间范围内有没有出现过,如果出现过,那么这条记录就必须丢弃了。UV 是有时间周期的概念的,比如日 UV、小时 UV、分钟 UV、月 UV 等。
(5)指标聚合
在完成了上述的所有过程后,终于要进行指标的计算了。计算的方式包括求和、平均值、最大值、最小值、95 百分位。
(6)结果写出
就是指把计算的指标的结果输出到各种存储或者通过接口发送给 mPaaS 的客户。目前我们的计算方式有三大类,实时计算、即时计算和离线计算。下面我会介绍这三种计算方式。
- 实时计算
实时计算模式:接收到日志后,模型立即开始进行计算,数据结果将在N分钟(N<=2)内产出,延迟非常的低。
推荐用作实时计算的技术选型包括:1) Flink 2) Spark 3) Storm (阿里做的 JStorm) 4) akka;其中 akka 适合用作业务逻辑较轻的实时监控和报警;关键的业务大盘、日志翻译回放这些都用 Flink 做比较好。
简单总结如下:
实时计算的优势是产出结果速度快、资源消耗少、灵活度中等;
实时计算的劣势是学习曲线相对陡峭、维护成本较高、配置复杂度高。
- 离线计算
离线计算模式:接收到日志后,直接保存下来,不做任何处理。待日志量积攒一段时间后,模型可进行一次性处理多日或者多月的日志数据。
推荐用作实时计算的技术选型包括: 1) Flink 2) Spark 3) Hive 4) Hadoop;大家看到了 FLINKSPARK 也出现在了实时模型的推荐技术选择中。这两个技术呢,分别从不同的起点出发,达到了相同的终点。
Flink 一开始是只做实时计算的,后来他开始提供批量离线计算能力;Spark 则正好相反。我们目前呢,还是充分利用每个技术栈的最大优势,离线还是选择 Spark,而不是 Flink。在这里多说两句,之前有一个经典架构是 “Lambda”模型,是指实时计算的结果要在离线里面再算一遍,这是因为之前总会出现实时计算丢数据、计算不准的情况,所以实时计算出来的结果只是用来观察一个趋势,再等第二天用离线的结果做补充,从而确保业务方能够看到准确的数据。但是在谷歌的 data-flow 计算模型的论文出来之后,目前市面上的实时计算引擎都具备了 "exactly-once" 的计算能力,换句话说,实时计算不会再出现丢数据以及计算不准的问题了。目前虽然还有“Lambda”模型,即数据会流向实时计算、离线计算两个引擎,但是离线不再是为实时计算做补充,而是为了充分利用它的性能,计算多日、多月的指标。
简单总结如下:
离线计算的优势是 计算性能高、学习难度低;
离线计算的劣势是 消耗资源大、延迟高、灵活度偏低。
- 即时计算
即时计算模式:接收到日志后,只做简单的预处理,比如日志切分,之后就直接入库。在需要展示界面的时候,根据用户配置的过滤和聚合规则即时进行数据处理。
推荐用作即时计算的的技术选型包括: Clickhouse (来自俄罗斯 yandex)、Apache Druid (来自 MetaMarket)、 Pinot (来自 :LinkedIn)。支付宝内部将即时计算模型应用到下钻分析、漏斗分析这些场景中,有时候也直接把它当做 OLAP 数据库使用。
简单总结如下:
即时计算的优势是超高灵活度、任务维度UV聚合、无限下钻能力、交付式的查询延迟(15s内)、学习成本低;
即时计算的劣势是资源消耗巨大、延迟中等无法用于做实时监控与报警、维度成本高,结构复杂。
这是目前支付宝内部的一个即时计算框架的技术架构图。从图中可以看出来目前即时计算的技术架构包括用来接收数据写入的实时日志节点(Read-time Nodes)、用于存储历史数据的深度存储(HDFS、AFS、OSS 等多种类型)、用来对历史数据(一天以前的数据)提供查询分析能力的历史节点(historical)。这个计算框架完全的支持 MySQL 协议,用户可以直接用 MySQL 客户端对其进行操作。还有一个重要特性是,他可以对任意的外部数据联合进行分析。
- 日志处理模型
我们再总结一下三种计算模式:
实时计算模型:数据摄入后立即按照预定规则执行计算,并在N分钟内产出需要的计算结果。
适用场景: 实时监控预警、链路追踪
优势: 消耗资源少、产出速度快
劣势: 配置复杂度高,灵活度低
离线计算模型:数据摄入后积攒N 小时/天 后按照预定规则进行批量处理。
适用场景: 用户分群、数据集市
优势:性能高、学习成本低
劣势: 延迟高、灵活度低
即时计算模型:数据摄入后只做简单的预处理立即入库,待查询时根据查询需求实时计算出指标。
适用场景: 下钻分析、漏斗分析
优势: 灵活度高、学习成本低
劣势: 资源消耗巨大、延迟中
希望大家能够根据我们的推荐选择适合的技术栈。
- 动态埋点
说完了我们目前的埋点类型、埋点计算模型,下面来说一下我们目前在内部使用的下一代埋点框架,动态埋点。
我们先针对以上四个问题进行思路串联,每个问题我也给出了相应的思路和解决办法。那么,这些答案是针对以上问题的最优解或者唯一解吗?很显然不是,因为这些解法都会带来开发量。而对于客户端来说,新的开发量就要发布版本,同时开发新的埋点,也可能会导致 App 内部的埋点臃肿不堪。
什么是动态埋点呢?有三个核心概念1) 埋点集、2) 动态埋点上报规则、3) 指标计算动态配置。
有了以上三项能力和配置,我们便可以根据现有的埋点集来配置某个链路的监控埋点,并依据这个复杂埋点来定义具体的指标的计算规则,从而做到不用增加开发量,同样可以快速监控新的指标的效果。不仅如此,我们还能够让埋点变成一种通用的资源,让大家更好地去使用它,而不是无谓地增加埋点,使得代码变得更臃肿。
让我们一起看一下动态埋点框架的一些 UI 交付图。
相应的,我们再对焦看一下支付宝埋点相关的应用服务:实时日志拉取。其中,它的主要技术框架包括了 mPaaS 里面的 MPS (消息推送)、MSS(数据同步)、以及日志网关。这是因为蚂蚁系 App 会与 MPS (安卓系统)、MSS (苹果系统) 保持长连接,在需要实时拉取日志的时候,用户可以在 mPaaS 的控制台上面通过这两个渠道下发指令,然后客户端就会把加密的明细日志全部上报到日志网关。
这是实时日志拉取的界面操作展示图。
针对于非常重要的性能指标: 闪退、卡顿、卡死, mPaaS 根据多年经验准备了对应的大盘。如图所示,上半部分是每分钟的闪退数,下面是我们根据闪退分类算法梳理出来的各个闪退分类情况,针对每个分类大盘里我们还能看到具体的设备分布情况。
最后,让我们从逻辑结构上再梳理一下 mPaaS 的服务端结构。mPaaS 包含五个核心组件:
1) MGS(网关服务):将客户端的请求转发到业务服务器.
2) MDS(发布服务):为客户端提供多种资源的多种灰度策略发布能力。
3) MPS & MSS(消息推送和数据同步服务):以长连接为基础,来提供数据下发能力。
4) MAS,(分析服务):也是今天讲解的重点,以日志埋点为基础的分析能力。
如果大家对 mPaaS 的移动分析服务感兴趣,欢迎点击文档地址 了解更多详情。
往期阅读
关注我们公众号,获得第一手 mPaaS 技术实践干货
钉钉群:通过钉钉搜索群号“23124039”
期待你的加入~