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

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,恶意文件检测 1000次 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日志并进行多维度分析。
目录
相关文章
|
2天前
|
存储 缓存 Java
浅析JAVA日志中的几则性能实践与原理解释
本篇文章通过几个技术点说明日志记录过程中的性能实践,计算机领域的性能往往都遵循着冰山法则,即你能看得见的、程序员能感知的只是其中的一小部分,还有大量的细节隐藏在冰山之下。
693 1
|
2天前
|
应用服务中间件
执行 ABAP 代码出现超时的原因,背后的理论和解决方案
:执行 ABAP 代码出现超时的原因,背后的理论和解决方案
19 0
|
9月前
|
存储 监控 数据可视化
01.崩溃捕获设计实践方案
01.崩溃捕获设计实践方案
135 3
|
10月前
|
存储 负载均衡 应用服务中间件
项目实战典型案例17——环境混用来带的影响
项目实战典型案例17——环境混用来带的影响
60 0
|
10月前
|
存储 应用服务中间件 测试技术
【项目实战典型案例】17.环境混用带来的影响
【项目实战典型案例】17.环境混用带来的影响
|
10月前
28个案例问题分析---08---让软件的使用者成为软件的设计者--思想
28个案例问题分析---08---让软件的使用者成为软件的设计者--思想
43 0
|
11月前
|
SQL 安全 测试技术
【解决方案 二十七】如何安全稳定的Dump线上数据
【解决方案 二十七】如何安全稳定的Dump线上数据
131 0
|
2天前
|
存储 运维 监控
日志服务 Scan 功能工作机制与最佳实践
大数据快速增长的需要泛日志(Log/Trace/Metric)是大数据的重要组成,伴随着每一年业务峰值的新脉冲,日志数据量在快速增长。同时,业务数字化运营、软件可观测性等浪潮又在对日志的存储、计算提出更高的要求。从时效性角度看日志计算引擎:数仓覆盖 T + 1 日志处理,准实时系统(搜索引擎、OLA...
46 0
|
XML 消息中间件 JSON
不接受反驳,性能最强,功能最强的Java日志框架
Logback 算是JAVA 里一个老牌的日志框架,从06年开始第一个版本,迭代至今也十几年了。不过logback最近一个稳定版本还停留在 2017 年,好几年都没有更新;logback的兄弟 slf4j 最近一个稳定版也是2017年,有点凉凉的意思。 而且 logback的异步性能实在拉跨,功能简陋,配置又繁琐,远不及Apache 的新一代日志框架 - Log4j 目前来看,Log4j2 就是王者,其他日志框架都不是对手
|
移动开发 JavaScript 前端开发
前端性能优化实践之代码层面更改(3)
前端性能优化实践之代码层面更改(3)
139 0