本文作者:轻山
一.前言
关联阅读 网易云音乐大前端监控体系(Corona)建设实践-开篇 。
Corona 是网易云音乐的大前端监控产品。Corona 的 SDK 在应用中捕获到各种类型日志后,经由上报、采集、分流链路到达 Corona 的消费服务进行处理。这条链路会直接影响到数据实时性和系统稳定性,如何高效、稳定、便捷的将应用产生的日志交由服务端消费就显得尤为重要。本文详细介绍 Corona 中的这条链路的设计与实践。
二.在 Corona 整体架构中的位置
在系统架构中,日志上报、采集、分流链路所处的位置如下(图中蓝色部分):
整条链路是在网易集团&云音乐的公共服务基础上做的能力整合,同时为了能够服务于集团其他事业部或者在其他事业部私有化部署,对依赖的云音乐服务节点做了可替换的设计。本文内容是这条链路进行详细的展开介绍。
三.具体实现
3.1 通过云音乐日志服务上报日志
Corona 各端 SDK 通过云音乐日志上报服务提供的 http 接口上报日志
云音乐的应用通过日志服务上报日志的链路如下:
其中:
网络层
- 不同类型的应用上报日志的方式是差异化的,比如 Android、iOS 应用是每产生一条日志就写入到本地文件,然后异步的把日志文件上传到日志服务,而 Web 前端应用是以普通的 HTTP POST 请求上传;
- 日志服务的接口设计了业务专属域名,命名规则就是在各个业务的主域名上添加约定的前缀。因为各个业务的 Cookie 是种在主域名下的,这样设计可以使得 SDK 采集日志后自动携带 Cookie 上报,从而使得日志信息更加丰富。
日志传输层
日志服务集群接收到不同业务、不同应用类型上报的日志后,首先会对日志做预处理,包括:
- 解压缩日志文件(来自 Android、iOS 等应用)、解密日志(有些加密上报的场景),最终使得各个来源的日志格式是一致的;
- 解析 Cookie,获取用户信息(UID)等业务数据塞入日志;
- 解析 ip 塞入日志;
- 记录日志上报到服务器的时间;
- ...
- 日志预处理完成后,会先暂存在服务器本地磁盘中。为了方便日志传输到不同的目的地,会根据
日志类型
、应用类型
、业务
等关键信息进行归档后写入到不同的日志文件。
这条链路属于云音乐专属的日志上报通道,为方便业务接入使用做了一些定制设计(比如业务专属日志域名)。
3.2 日志采集服务
上文讲到应用的日志上报后存储在日志服务集群的本地磁盘上,如何高效、稳定、便捷的采集这些日志就显得尤为重要。Corona 使用网易集团数据科学中心自研的一款日志采集服务实现日志实时采集、ETL 归档等功能。
如图所示,Agent
是日志采集服务核心的采集程序,部署在云音乐日志服务集群的应用服务器上,用户通过管理后台进行 Agent 管理,并由 Manager Service 下发采集规则到 Agent 程序。
采集规则是稳定的、极少变动的,会将一个业务下所有日志都采集上来,即使新增的日志类型也会被自动采集,尽量避免变更采集规则而对上层应用造成不可预知的风险。
Agent 程序会根据规则读取指定文件的日志,记录文件采集位置,并将采集到的日志送往 2 个目的地:
- DWD 明细数据层,是一个 HBase 数据库,用于原始日志的备份、提供给数据分析师使用、或者开放给开发者自助分析;
- 写入 kafka 消息队列,经过一系列流转后最终会流入 ADS 层数据库(应用数据层),被 Corona 的日志消费服务订阅;这里不同的业务和日志类型会有专属的 kafka topic,这样设计的原因是因为方便在云音乐内部给业务其他服务、产品去订阅消费,做一些自定义的功能、业务指标统计等;
以上是对日志采集过程的简单介绍,想了解日志采集服务更多细节的同学可以查看 Apache 的顶级开源项目 flume。
3.3 面向数据消费层实现日志分流
3.2 中由日志采集服务写入 kafka 的日志,包含一个业务(or 应用)所有监控日志类型,比如设备活跃日志、异常日志、性能日志等,并且这个日志种类非常动态,随时会因为新增监控指标而增加。Corona 的架构设计里,在数据消费层不同类型的日志有不同的消费服务,如果让每个消费服务直接订阅上述 kafka topics 的话,会带来极大的资源浪费以及稳定性风险,假设有如下 2 个业务场景:
如图所示,每个消费服务能承载的日志流量上限,必需按所有日志类型的累计流量来设计,在服务内部用代码逻辑过滤丢弃不需要的日志,并且一旦某个日志类型出现了流量突增,那么所有消费服务都需要承担流量峰值带来的风险。
为了解决这个问题,Corona 使用 Flink 对日志做分流,确保到达应用层各个消费服务的日志是单个消费服务所需要的日志。Flink 实时计算能力由 云音乐数据平台 提供。
用 Flink 实时任务实现日志分流的过程如下:
从日志服务集群上、按业务采集的日志会流入一张流表中,然后 Flink 实时流任务根据下游不同消费服务的需要去流表中查询相关日志。可以简单理解为,Corona 针对异常监控、性能监控、实时流量监控场景有 3 个日志消费服务,Flink 会根据这 3 个服务所需要的日志类型去查询日志,然后写入 3 个新的消息队列。
至此,每个消费服务承接的流量就变成了下图:
每个消费服务在设计时只需要考虑相关日志类型的流量上限。一方面减少了服务器资源的浪费,另一方面单一日志类型的突增也只会影响单个消费服务的稳定性,不会导致整个系统不可用。
3.4 极端大流量的应对措施
经过上述日志分流任务处理后,虽然已经保证了单一日志类型的突增只会影响单个消费服务的稳定性,但单个消费服务的宕机也会导致产品部分功能不可用,这对于用户来说是不可接受的,也不符合监控产品本身高可用的目标。
前置链路中日志异步采集以及 kafka 消息队列已经能够起到削峰的作用,但在极端大流量下还不足以保障下游应用的稳定性以及实时性。
在经历多次线上日志流量异常突增的紧急处理之后,目前 Corona 在日志链路层采取以下应对措施:
- 数据消费服务增加日志类型流量监控、告警;
- 收到告警后,在 Flink 分流任务中,配置针对大流量日志的过滤规则,直接丢弃;
日志分流任务计算逻辑比较轻量,因此对流量并不敏感,而且 Flink 的实时任务扩容很方便,无需运维参与,开发者直接调整参数重启即可。
以上过程需要开发者参与响应流量告警,因为极端大流量场景比较少见,所以人工响应成本并不大。
在 Corona 的消费服务设计中,也开放支持用户自主设计过滤规则、丢弃应用日志,同时应用层的服务也有针对日志波峰的自动响应策略,在本文中不作展开介绍了,未来会有专门文章介绍消费服务的设计。
至此,对上述日志分流链路图略作补充,增加极端大流量的响应、处理链路:
3.5 独立日志上报通道
3.1 所述的日志上报链路属于云音乐专属通道,有方便云音乐业务接入使用的定制设计,并不适合集团其他事业部接入。出于未来商业化考虑,为了能快速接入其他 BU 的应用,Corona 也提供了独立的日志上报服务。
Corona Log Receiver 是一个 Node.js 应用,上报到此服务的日志并不会携带业务方的 Cookie。如果接入方需要更多业务信息(比如用户 id 等信息),可以使用 SDK 提供的 api 进行全局设置(在介绍 SDK 的文章中会详细展开),之后 SDK 在上报日志时就会携带这些额外信息。
Corona Log Receiver 在接收到日志后会将额外信息与原始日志进行重组、以及添加用户 ip 信息等操作,然后将日志写入独立的 kafka topic,直接对接分流服务。
我们对上述数据流图略作补充,得到以下的 Corona 日志上报、采集、分流链路图:
四.总结
本文分 5 小节介绍了云音乐大前端监控产品 Corona 的日志上报、采集、分流链路,以及极端大流量场景下的应对措施。将以上内容串联后可以得到以下完整的日志流转链路图:
本文是 Corona 技术专题的第二篇,欢迎大家多多交流。
本文发布自网易云音乐技术团队,文章未经授权禁止任何形式的转载。我们常年招收各类技术岗位,如果你准备换工作,又恰好喜欢云音乐,那就加入我们 grp.music-fe(at)corp.netease.com!