zl程序教程

您现在的位置是:首页 >  其他

当前栏目

阿里百度华为等大厂是如何追踪微服务调用的?

百度阿里华为服务 如何 调用 大厂 追踪
2023-09-27 14:19:47 时间

1 服务追踪系统的意义

1.1 快速定位请求失败原因

微服务架构下,服务众多,如果一次上游请求失败,想查清楚到底是哪个应用导致,简直是梦魇!

倘若有一系统,可跟踪记录一次用户请求都发起了哪些调用,经过哪些服务处理,并且记录每一次调用所涉及的服务的详细信息,调用失败,不就可通过日志快速定位问题环节!

1.2 优化系统瓶颈

通过记录调用经过的每一条链路上的耗时,能快速定位整个系统的瓶颈点。比如你访问xxx网站首页发现很慢,可能是运营商网络延迟、网关系统异常、某服务异常、缓存或DB异常。通过服务追踪,可在上帝视角观得整个系统的瓶颈点,再针对性优化。

1.3 优化链路调用

分析调用所经过的路径,评估是否合理,是否每个依赖都是必要,是否可通过业务优化减少服务依赖。

一般业务都会在多个数据中心都部署服务,以实现异地容灾,这时经常会出现服务A调用另外一个数据中心的服务B,而没有调用同处于一个数据中心的服务B。
跨数据中心的调用视距离远近都会有一定网络延迟,对于有些业务不可接受。通过分析调用链路,可找出跨数据中心的服务调用,从而优化。

1.4 生成网络拓扑

通过记录的链路信息,可以生成一张系统的网络调用拓扑图,它可以反映系统都依赖了哪些服务,以及服务之间的调用关系是什么样的,可以一目了然。
在网络拓扑图上还可把服务调用的详细信息也标出来,也能起到服务监控的作用。

1.5 透明传输数据

业务上经常有一种需求,期望能把一些用户数据,从调用的开始一直往下传递,以便系统中的各个服务都能获取到这个信息。比如业务想做一些A/B测试,就想通过服务追踪系统,把A/B测试的开关逻辑一直往下传递,经过的每层服务都能获取到这个开关值,就能统一A/B测试。

2 服务追踪系统原理

服务追踪系统鼻祖:Google的论文Dapper, a Large-Scale Distributed Systems Tracing Infrastructure详细讲解了服务追踪系统的实现原理。

  • 核心理念
    调用链,通过一个全局唯一ID串联分布在各个服务节点上的同一次请求,还原调用关系,可追踪系统问题、分析调用数据并统计各种系统指标。
    之后诞生的各种服务追踪系统都是基于Dapper,比如Twitter的Zipkin、阿里的鹰眼、美团的MTrace等。

2.1 核心概念

traceId

一次分布式调用的链路踪迹。全局唯一,64位整数,用于标识某次具体请求ID。
在RPC调用的网络链路中不断传递,串联某一次请求在系统中经过的所有路径。

spanId

一个方法(局部或远程)调用踪迹。用于标识一次RPC调用在分布式请求中的位置,区分系统不同服务之间调用的先后关系。
当用户的请求进入系统后,处在RPC调用网络的第一层A时spanId初始值是0,进入下一层RPC调用B的时候spanId是0.1,继续进入下一层RPC调用C时spanId是0.1.1,而与B处在同一层的RPC调用E的spanId是0.2,这样的话通过spanId就可以定位某一次RPC请求在系统调用中所处的位置,以及它的上下游依赖分别是谁。这类似哈夫曼编码。

annotation

附着在 Span 上的日志信息。用于业务自定义埋点数据,可以是业务感兴趣的想上传到后端的数据,比如一次请求的用户UID。
业务自定义一些自己感兴趣的数据,在上传traceId和spanId这些基本信息之外,添加一些自己感兴趣的信息。

Sampling

采样率。

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