3 服务追踪系统实现
- 服务追踪系统的架构
- 服务追踪系统可以分为三层:
- 数据采集层,负责数据埋点并上报
- 数据处理层,负责数据的存储与计算
- 数据展示层,负责数据的图形化展示
3.1 数据采集层
在系统的各个不同模块中进行埋点,采集数据并上报给数据处理层进行处理。
那么该如何进行数据埋点呢?结合下面这张图来了解一下数据埋点的流程。
以红色方框里圈出的A调用B的过程为例,一次RPC请求可以分为四个阶段。
CS(Client Send)阶段 : 客户端发起请求,并生成调用的上下文
SR(Server Recieve)阶段 : 服务端接收请求,并生成上下文
SS(Server Send)阶段 : 服务端返回请求,这个阶段会将服务端上下文数据上报,下面这张图可以说明上报的数据有:traceId=123456,spanId=0.1,appKey=B,method=B.method,start=103,duration=38。
CR(Client Recieve)阶段 : 客户端接收返回结果,这个阶段会将客户端上下文数据上报,上报的数据有:traceid=123456,spanId=0.1,appKey=A,method=B.method,start=103,duration=38。
3.2 数据处理层
把数据采集层上报的数据按需计算,然后落地存储供查询使用。
据我所知,数据处理的需求一般分为两类,一类是实时计算需求,一类是离线计算需求。
实时计算需求对计算效率要求比较高,一般要求对收集的链路数据能够在秒级别完成聚合计算,以供实时查询。而离线计算需求对计算效率要求就没那么高了,一般能在小时级别完成链路数据的聚合计算即可,一般用作数据汇总统计。针对这两类不同的数据处理需求,采用的计算方法和存储也不相同。
实时数据处理
针对实时数据处理,一般采用Storm或者Spark Streaming来对链路数据进行实时聚合加工,存储一般使用OLTP数据仓库,比如HBase,使用traceId作为RowKey,能天然地把一整条调用链聚合在一起,提高查询效率。
离线数据处理
针对离线数据处理,一般通过运行MapReduce或者Spark批处理程序来对链路数据进行离线计算,存储一般使用Hive。
3.3 数据展示层
数据展示层的作用就是将处理后的链路信息以图形化的方式展示给用户。
主要用到如下两种图形展示:
调用链路图
- Zipkin的调用链路图
- 通过该图可以看出:
服务整体情况
服务总耗时、服务调用的网络深度、每一层经过的系统,以及多少次调用。上图的一次调用总共耗时209.323ms,经过5个不同的系统模块,调用深度为7层,共发生了24次系统调用。
每一层的情况
每一层发生了几次调用,以及每一层调用的耗时。
调用链路图在实际项目中,主要是被用来做故障定位,比如某一次用户调用失败了,可以通过调用链路图查询这次用户调用经过了哪些环节,到底是哪一层的调用失败所导致。
调用拓扑图
- Pinpoint的调用拓扑图,通过这张图可以看出系统内都包含哪些应用,它们之间是什么关系,以及依赖调用的QPS、平均耗时情况
- 调用拓扑图是一种全局视野图,在实际项目中,主要用作全局监控,用于发现系统中异常的点,从而快速做出决策。比如,某一个服务突然出现异常,那么在调用链路拓扑图中可以看出对这个服务的调用耗时都变高了,可以用红色的图样标出来,用作监控报警。
参考
http://bigbully.github.io/Dapper-translation/
https://tech.meituan.com/2016/10/14/mt-mtrace.html