10个特性:这才是你需要的Trace方案

本文涉及的产品
对象存储 OSS,20GB 3个月
日志服务 SLS,月写入数据量 50GB 1个月
对象存储 OSS,恶意文件检测 1000次 1年
简介: 分布式链路追踪(Distributed Tracing,简称Trace)又名全链路数据追踪,为业务系统提供了整个服务调用链路的调用关系、延迟、结果等信息。本文主要介绍Trace方案的一些高级特性,让大家可以更好的使用Trace来解决业务可观察性的问题。

为什么需要Trace

在现代IT系统,尤其是云原生、微服务系统中,一次外部请求往往需要内部多个服务、多个中间件、多台机器的相互调用才能完成。在这一系列的调用中,任意阶段出现的问题都可能导致外部服务失败或延迟升高,最终影响用户体验。在这种情况下,若想要精确分析并定位具体服务、模块、机器,你需要知道服务调用的关系是怎样的,错误是怎么传播过来的,具体是哪块的延迟比较大...这些Trace全部都可以告诉你。

image.png

Trace是什么

分布式链路追踪(Distributed Tracing,简称Trace)又名全链路数据追踪,为业务系统提供了整个服务调用链路的调用关系、延迟、结果等信息。相比访问日志这种记录顺时请求结果的数据,Trace则把内部的各种请求连接起来,组成一个服务调用的关系图,让你能轻松知道服务是怎么发起的、怎么流转处理的。


image.png

ServiceC

ServiceB

口一*一07

ServiceD

ServiceA

ServiceE

Queue

ServiceF

冰山一角:一个典型的Trace表示

image.png

Fig1:High-levelstructureofservices

Fig2:ATransactionasanend-o-dqe-oecle

User

ip-service

api-service

weather-service

IP

service

api-service

weather

User

service

Fig3:ATraceastherecordofaTransaction

Fig4:ATraceisaDAGofSpans

user

Oms

50ms

200ms

whereami

user:GET/whereami

childof

api-server

api-server:GEt/whereami

whereami

api-server:GET/ip-service

childof

childOf

api-server:GEr/weather-seryice

api-server

api-server

GETip-service

GETwEAtHER-ServiCE

上述是一个非常简单的程序,用户访问网站的时候自动给他们展示用户所在地的天气情况,这就需要调用两个外部的服务。整个交互过程如上午的1、2所示。:首先获取远端的IP地址,调用IP服务获取IP对应的地域信息;获取到地域信息后,调用天气服务查询对应地点的天气,最后返回给用户。


这个典型的调用也可以理解为一个Transaction,也就是端到端的请求->返回的过程,对于用户来说,就是一个简单的页面/接口请求,内部经历的每个请求->返回的记录就是Trace。图3是一个典型的Trace调用展示,从这个图中,可以看到请求整体的耗时、调用的接口、每个接口的耗时等信息。通过这种图形化的方式,就可以很容易的找到是哪个请求耗费了太多的时间,或者那个请求出现了错误。而图4是通过Trace信息还原出的DAG图,能够反映出系统中服务的依赖路径,能够更加清晰的了解系统。


上述就是一个最简单的Trace表示,也是Trace最开始的状态,能够表示一个请求具体的调用路径以及调用的详细信息,具备一定的可视化能力来辅助查看。当然Trace的能力还不仅仅于此,下面我们会详细展开真正友好的Trace方案所需具备的各项能力。

1. Trace标准化-OpenTelemetry

image.png

而无论图3还是4都是依赖Trace的“父子关系”来构造出来,而这个关系主要有Trace的组成Span而来(Trace Span的概念最早来自于Google的Dapper)。

  • Trace记录了整个请求的生命周期,本身由一组Span组成,Span代表其中的一条调用链
  • Span具有“父子关系”,这个父子关系由SpanID和ParentSpanID组成
  • 当调用传播到下一层时,原来的SpanID就变成了ParentSpanID,随后会生成一个新的SpanID
  • Span的传播可能会跨进程、跨主机,因此需要有一个传递TraceID、SpanID的途径,这个途径叫做Trace Propagation,Trace Propagation需要保证上下游的服务都能够支持一样的协议才行,否则传播到下一层时,因为服务无法识别,Trace会断掉。
  • 由于系统中可能具有多个服务,还有队列、数据库、ServiceMesh等中间件,因此Trace Propagation需要遵循某个国际化标准,这个标准需要尽可能的通用。
  • 最早在出现的国际化标准是OpenTracing,随后还有Google发起的OpenCensus项目
  • 而目前OpenTracing项目和OpenCensus项目已经合并成为OpenTelemetry,OpenTelemetry已经成为Trace领域的唯一国际化标准。


而OpenTelemetry标准带来的好处不仅仅是解决各个系统之间的Trace互通问题,还有统一的SDK、自动化埋点方案、数据采集、Traces/Metrics/Logs互通等等好处。感兴趣的同学可以异步:OpenTelemetry介绍


2. 埋点:手动 or 自动

对于开发者来讲,使用Trace最大的工作量是接入数据,我们需要在请求发起的时候创建一个Span,并且这个Span需要继承上一个Span传过来的TraceID、ParentSpanID等信息。下述代码就是一个简单的手动构造Trace的例子:

/* api-service */app.use('/api/v1/whereami', async (req, res, next) => {
constparentSpan=createContinuationSpan(tracer, req, 'whereami-request')
constchildSpan=tracer.startSpan('city-from-ip', {childOf: parentSpan})
const_=awaitaxios.get(`http://ip-api.com/json/${req.ip}`)
childSpan.finish()
// Do more work and create more children spans.parentSpan.finish()
})
functioncreateContinuationSpan(tracer, req, spanName) {
constincomingSpanContext=tracer.extract(opentelemetry.FORMAT_HTTP_HEADERS, req.headers)
if (incomingSpanContext==null) {
returntracer.startSpan(spanName)
    }
returntracer.startSpan(spanName, {childOf: incomingSpanContext})
}

对于一个庞大的系统而言,业务中涉及的请求非常多,每个请求都手动埋点的工作量太大,一般这种方式也很难在公司进行推广,因此各类语言的自动埋点的方式开始蓬勃发展。自动埋点在Trace领域又叫做Trace Instrumentation,主要利用一些代理、装饰器、代码注入、AOP等技术,在请求处理之前产生Span,在请求处理完成后保存Span并自动发送到Trace服务端。


下述是一个常见的服务架构,Service A和Service B都是HTTP的服务实现,网络通信使用ServiceMesh进行流量管理,HTTP请求都会经过HTTP框架进行处理,然后提交到Dispatcher模块,该模块会根据不同的URL转发到对应的Hander进行处理。这一架构中,可以自动埋点的地方有3个:

  1. ServiceMesh层,所有的HTTP请求在处理的时候都进行埋点
  2. HTTP Framework,在HTTP请求接收、处理的过程中埋点
  3. Dispatcher,在转发的时候进行埋点


image.png


一般而言,自动埋点也可以在多层同时进行,这样可以获取到每层对于性能的消耗是多少,对整体架构的性能开销有个更准确的理解。在生产上绝大部分情况都是使用自动埋点,对于有些自动埋点不能覆盖的场景,会用手动埋点的方式进行补全。例如某些语言不支持自动埋点、某个请求内部处理逻辑复杂需要手动创建子Span分成多个阶段...


自动埋点

手动埋点

工作量

支持的场景

全面

Trace完整度

性能开销

较高


3. 基于Trace的监控

我们知道Trace由Span组成,Span表示了当前某个调用的结果以及“父子”关系,而当某个Service的某个调用积累一定数量的时候,我们就可以分析出这个Service、调用的一些关键指标:访问次数(QPS)、延迟、错误率等。而这些通常也代表着我们的服务是否正常,因此通常情况下Trace不仅仅用来去查看某个请求是否有问题,更多的时候会用来监控服务是否正常。

image.png


4. PXX延迟-业务真实体验

基于Trace的监控不是从聚合指标而来,而是从每个调用来去计算出相应的访问次数、延迟、错误率,从原始数据计算的一个优点是可以较为准确的统计出PXX延迟,而PXX延迟也是反应用户对于我们业务真实体验的一个重要指标。因为通常情况下,平均延迟只能说明服务的情况,而不代表所有的客户访问都是如此的延迟,如果有一小部分的客户访问延迟很高,整体的平均延迟不会增加很多,但是这部分客户对于产品的体验会下降很多。

image.png


因此我们会更加关心P90、P95、P99之类的延迟指标,也就是按延迟正序排列,位于90%、95%、99%分位数的延迟大小。这部分延迟如果比平均延迟大非常多,那说明我们的服务在某些场景下对部分用户的体验非常不好,而这种情况下就需要去看这部分高延迟的指标具体耗时在哪个阶段,并进行针对性解决。


image.png

9othPercentilevalue

HTTPRequest

90%

10%

ResponseTime

5. 高级Dependency分析

Dependency作为Trace的核心功能,是分析系统架构的利器,通过大数据工程(一般使用流计算、批量计算)分析所有上报的Span信息,将其中公共的关系提取、聚合,然后保存成一张DAG图。通常Dependency都只是从服务、调用维度进行计算,主要是因为这种计算的资源消耗比较少,毕竟服务、调用的组合比较少。


而实际场景中,我们希望知道在某个时间段、某一个进程、某一组容器的依赖关系,这就需要针对Span的Resource信息进行提取计算,组合关系会提升1-2个数量级,而计算复杂度和资源消耗也会随之提升。但带来的好处非常明显,我们能够知道更加细粒度的依赖关系,也更容易找出问题所在的机器、进程。


同时,在Dependency分析中,不仅仅只是计算DAG图的关系,而且还可以计算每个父子关系(也就是DAG图的边)的统计信息,包括调用次数、错误率、延迟等。因此在查看Dependency的时候,还可以看到某个节点调用其他服务的统计信息,更加有利于问题排查。

image.png

6. Trace自定义过滤

通常为了更好的分析Trace数据,我们都会在Span中附加一定的Tag信息,如果更精确的描述,Tag分位两类,分别Resource和Attribute。在OpenTelemetry协议中,这两种数据虽然都是同一数据类型,但含义却有着很大的不同:

  • Resource代表Span的宿主信息描述,例如进程名、主机名、IP地址、设备类型、版本号、服务名、DB类型、K8s Pod名、环境信息、云相关信息,相对都是静止的信息。
  • Attribute标识Span产生时和调用相关的属性信息,例如HTTP的方法、返回码、InFlow、OutFlow、URL、DB请求的SQL、数据队列请求的Topic信息等。

通常我们都需要按照不同的Resource、Attribute来过滤出我们关心的数据,用来定位问题主要发生在哪些类型的调用中。当然除了对这些Tag信息支持过滤外,还需要对Trace的其他属性,例如延迟、状态码、Span附加的Event信息等支持过滤。

image.png

7. Trace自定义分析

如果把Trace的自定义过滤功能比作是千里眼,则Trace的自定义分析功能就是显微镜。Trace自定义过滤从茫茫的数据中发现感兴趣的一部分Trace数据,而自定义分析对这部分Trace数据进行详细的排查,找出其中有问题的那一部分。这里的分析主要利用统计学相关的技术,按照不同的维度组合去分析,而这些维度包括上述的任一Resource和Attribute信息,从中去发现异常的维度。

image.png

依效分析

Trace分析

分组统计:operation+1x

平均廷迟

Span个发

键误率

QPS

P90连迟

P50江远

P95诞迟

P9E

stal

operalon

OK

722

.

1.78ms

1.78ms

1.78m3

1.78ma

0%

1.78ms

6

OK

0%

6.9ms

23904

GETcuslorcrs

6.9ms

6.9m

0%

OK

1

GETICETAIOGLETID

2.33ms

5978

2.33ms

2.33m

2.33ms

2.33ms

oK

0%

GET/ogIn

5.79ms

5984

5.79m

5.79ms

5.79ms

5.79ma

OK

0%

5983

GETicade

3.88ms

3.8Gms

3.BGms

3.86ms

3.86m

0%

OK

POSTpaymentAuth

198.17US

198.17U5

198.17L8

198.17L3

198.17US

0%

OK

2.6m

GETicataloguo

6977

2.6ms

2.6ms

2.6ms

2.0ms

0%

GETYDDRESSCA

OK

3.94ms

3.94ms

5974

3.94ms

3.94ms

3.94ms

8. Trace自动化分析

上述的自定义分析主要是靠人工+统计学,这种方式在数据维度不多的情况下还可以胜任,但如果要分析的数据维度超过3个时,纯粹的手工分析已经很难去把每个组合都尝试一遍。例如某个支付类型的调用成功率出现了下降,这个调用有地域、设备版本号、运营商、会员类型、支付类型5个维度信息,手动来做的话需要按照5个不同的维度去一一尝试,找到其中某个有明显分界的维度,再保存这个维度的信息,继续向其他4个维度进行尝试,最坏的情况下需要5*4*3*2*1次的手动分析才能找到问题的组合。而这个还是在问题只是由一个组合影响,如果有多个组合综合产生的结果,手动分析会收到多个结果的影响而更加复杂。


因此这时候我们就需要用算力和算法去做自动化的分析,利用算力从海量的组合中去一一分析,结合算法进行有效的剪枝,最终快速的得到造成调用错误率提升、延迟升高的维度组合。

9. 可观察性数据关联

Trace可做的事情很多,但并不是万能的,Trace更多的是应用的关系数据以及从这些数据提取出的应用健康度(延迟、错误率、QPS等)数据。对于问题的根因分析还缺少一些关键的信息,包括与之关联的基础设施健康信息(例如Pod/主机核心指标、异常事件、内核报错等)以及应用的详细错误日志。这些通常情况下叫做Metrics、Logs数据。


为了能够让Trace更好的关联上述的其他数据,Trace中的Span必须包含对应的主机名、容器名、服务名等信息,也就是OpenTelemetry中的Resource信息。而且Trace方案需要提供快速跳转并查询对应数据的能力。

image.png

ttodt:tno

Zt97

looTYintougproyigptutht

Zuc915187

lor:tntowgproymgtquatht

Ztc1187

or:intogpouth

zt91

tattp

w20902009

4KO99946015276

N

Host

Service

TraceID

POSTYorderS

65

front-endserver

50

fegussthandlar-Lorders

nodcp

tront-andinternalHTTP

55

HTTPGET

21.18ms

50

HMTP

NODES

10

GETFcusTOMERS

HITP

userserver

8

HTTPGET

35

tHTTP

front-ondcliont

nodOp

80

GETFEUSTOMOrS

wserSererHMP

09:00

10:30

11:00

10:00

09:30

10. 自动根因定位

当我们能够将Trace关联到Logs和Metrics时,就能够“顺藤摸瓜”找到问题的根本原因,无论是某台机器硬件故障(机器内核日志定位)、资源饱和(指标数据定位)、应用错误(应用报错日志)...

这些问题的排查相比纯粹的Trace分析会更加复杂,需要与更多的系统交互,需要去查看更多的数据,因此所花费的时间也更久。而故障发生时,1分钟的损失也是难以接受的,因此我们需要更快的去发现这些问题,这时AIOps中的自动根因定位就派上了用场:利用Trace内部的“父子”关联关系以及Resource与Logs、Metrics的关联关系自动“顺藤摸瓜”去排查问题的根因所在,大大节省问题排查的时间,能够让问题的根因定位从小时/分钟级降低到秒级。

image.png

Definethe

ldentifyeffective

problem

Solutions

STEP1.

STEP2.

STEP3.

STEP4.

Determinethe

lmplementang

tracksolutions

causalrelationships


总结

随着云原生、微服务技术的普及,Trace在运维领域的重要性也越发的凸显,构造一个简单的Trace系统并不难,但如何构建一个能充分发挥Trace优势的系统难度很大。上述介绍的这些Trace的特性,在生产中都极其适用,有这些特性的加持,问题排查将变得更加简单,尤其是后面6-10的特性价值更高,实现难度也更大:

  • Trace自定义过滤和自定义分析能够帮助我们更好的去定位Trace相关的问题,这个能力要求Trace系统具备足够的强的存储、索引和算力。
  • 可观察性数据关联能够实现问题的根因定位,前提是需要所有的数据都能遵循一个统一的标准,而OpenTelemetry正是首选方案。
  • 自动化的根因定位能够缩短问题的排查时间,减少故障带来的损失,核心是AIOps算法需要具备超强的算力和更好的检测效果。


目前SLS已经发布了第一个版本的Trace服务,支持OpenTelemetry格式的Trace接入,并提供了上述1-7功能,后续功能的支持也在紧锣密鼓的研发中,欢迎大家试用。


传送门:https://sls.console.aliyun.com/lognext/trace

视频介绍:https://www.loom.com/share/8f13f0af46164b52a5e78e5b455ec622


附件已失效 Trace.mp4
|

参考

  1. https://opentelemetry.io/
  2. https://developer.aliyun.com/article/766070
  3. https://aiopsworkshop.github.io/
  4. https://landscape.cncf.io/
  5. https://github.com/apache/skywalking
  6. https://www.instana.com/blog/observability-vs-monitoring/
  7. https://www.katacoda.com/lokoms/scenarios/log-workshop-4
  8. https://wiprodigital.com/2020/04/30/how-aiops-impacts-business-performance/
  9. https://docs.lightstep.com/docs/view-traces
  10. https://docs.lightstep.com/docs/investigate-a-latency-regression
  11. https://www.jaegertracing.io/
  12. https://medium.com/jaegertracing/using-jaeger-to-trace-an-apache-camel-application-2b8118efbb4d
  13. https://github.com/apache/camel/blob/master/components/camel-opentracing/src/main/docs/opentracing.adoc
  14. https://www.sumologic.com/blog/logs-metrics-overview/
  15. https://www.novatec-gmbh.de/en/blog/5-reasons-why-opentelemetry-will-boost-observability-and-monitoring/


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
7月前
|
存储 监控 Java
【深度挖掘Java性能调优】「底层技术原理体系」深入探索Java服务器性能监控Metrics框架的实现原理分析(Counter篇)
【深度挖掘Java性能调优】「底层技术原理体系」深入探索Java服务器性能监控Metrics框架的实现原理分析(Counter篇)
172 0
|
7月前
|
存储 缓存 Java
浅析JAVA日志中的几则性能实践与原理解释
本篇文章通过几个技术点说明日志记录过程中的性能实践,计算机领域的性能往往都遵循着冰山法则,即你能看得见的、程序员能感知的只是其中的一小部分,还有大量的细节隐藏在冰山之下。
|
4月前
|
监控 Java API
分布式链路监控系统问题之Attach实现字节码增强的问题如何解决
分布式链路监控系统问题之Attach实现字节码增强的问题如何解决
|
5月前
|
缓存 Java
浅析JAVA日志中的性能实践与原理解释问题之AsyncAppender的配置方式的问题是如何解决的
浅析JAVA日志中的性能实践与原理解释问题之AsyncAppender的配置方式的问题是如何解决的
|
5月前
|
运维 中间件 数据库
浅析JAVA日志中的性能实践与原理解释问题之元信息打印会导致性能急剧下降问题如何解决
浅析JAVA日志中的性能实践与原理解释问题之元信息打印会导致性能急剧下降问题如何解决
|
设计模式 Java 关系型数据库
JAVA设计模式第十讲:SPI - 业务差异解决方案
JAVA设计模式第十讲:SPI - 业务差异解决方案
268 0
JAVA设计模式第十讲:SPI - 业务差异解决方案
|
设计模式 Java
JAVA设计模式7:适配者模式,彻底解决两不兼容接口之间的问题
JAVA设计模式7:适配者模式,彻底解决两不兼容接口之间的问题
173 0
|
存储 监控 数据可视化
01.崩溃捕获设计实践方案
01.崩溃捕获设计实践方案
193 3
|
SQL 安全 测试技术
【解决方案 二十七】如何安全稳定的Dump线上数据
【解决方案 二十七】如何安全稳定的Dump线上数据
187 0
|
存储 消息中间件 运维
一文详解|Go 分布式链路追踪实现原理
在分布式、微服务架构下,应用一个请求往往贯穿多个分布式服务,这给应用的故障排查、性能优化带来新的挑战。分布式链路追踪作为解决分布式应用可观测问题的重要技术,愈发成为分布式应用不可缺少的基础设施。本文将详细介绍分布式链路的核心概念、架构原理和相关开源标准协议,并分享我们在实现无侵入 Go 采集 Sdk 方面的一些实践。
1414 0
一文详解|Go 分布式链路追踪实现原理
下一篇
DataWorks