在现代IT系统 尤其是云原生、微服务系统中 一次外部请求往往需要内部多个服务、多个中间件、多台机器的相互调用才能完成。在这一系列的调用中 任意阶段出现的问题都可能导致外部服务失败或延迟升高 最终影响用户体验。在这种情况下 若想要精确分析并定位具体服务、模块、机器 你需要知道服务调用的关系是怎样的 错误是怎么传播过来的 具体是哪块的延迟比较大...这些Trace全部都可以告诉你。
Trace是什么分布式链路追踪 Distributed Tracing 简称Trace 又名全链路数据追踪 为业务系统提供了整个服务调用链路的调用关系、延迟、结果等信息。相比访问日志这种记录顺时请求结果的数据 Trace则把内部的各种请求连接起来 组成一个服务调用的关系图 让你能轻松知道服务是怎么发起的、怎么流转处理的。
上述是一个非常简单的程序 用户访问网站的时候自动给他们展示用户所在地的天气情况 这就需要调用两个外部的服务。整个交互过程如上午的1、2所示。 首先获取远端的IP地址 调用IP服务获取IP对应的地域信息 获取到地域信息后 调用天气服务查询对应地点的天气 最后返回给用户。
这个典型的调用也可以理解为一个Transaction 也就是端到端的请求- 返回的过程 对于用户来说 就是一个简单的页面/接口请求 内部经历的每个请求- 返回的记录就是Trace。图3是一个典型的Trace调用展示 从这个图中 可以看到请求整体的耗时、调用的接口、每个接口的耗时等信息。通过这种图形化的方式 就可以很容易的找到是哪个请求耗费了太多的时间 或者那个请求出现了错误。而图4是通过Trace信息还原出的DAG图 能够反映出系统中服务的依赖路径 能够更加清晰的了解系统。
上述就是一个最简单的Trace表示 也是Trace最开始的状态 能够表示一个请求具体的调用路径以及调用的详细信息 具备一定的可视化能力来辅助查看。当然Trace的能力还不仅仅于此 下面我们会详细展开真正友好的Trace方案所需具备的各项能力。
1. Trace标准化-OpenTelemetry而无论图3还是4都是依赖Trace的“父子关系”来构造出来 而这个关系主要有Trace的组成Span而来 Trace Span的概念最早来自于Google的Dapper 。
Trace记录了整个请求的生命周期 本身由一组Span组成 Span代表其中的一条调用链Span具有“父子关系” 这个父子关系由SpanID和ParentSpanID组成当调用传播到下一层时 原来的SpanID就变成了ParentSpanID 随后会生成一个新的SpanIDSpan的传播可能会跨进程、跨主机 因此需要有一个传递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介绍。
对于开发者来讲 使用Trace最大的工作量是接入数据 我们需要在请求发起的时候创建一个Span 并且这个Span需要继承上一个Span传过来的TraceID、ParentSpanID等信息。下述代码就是一个简单的手动构造Trace的例子
/* api-service */ app.use( /api/v1/whereami , async (req, res, next) { const parentSpan createContinuationSpan(tracer, req, whereami-request ) const childSpan tracer.startSpan( city-from-ip , {childOf: parentSpan}) const _ await axios.get( http://ip-api.com/json/${req.ip} ) childSpan.finish() // Do more work and create more children spans. parentSpan.finish() function createContinuationSpan(tracer, req, spanName) { const incomingSpanContext tracer.extract(opentelemetry.FORMAT_HTTP_HEADERS, req.headers) if (incomingSpanContext null) { return tracer.startSpan(spanName) return tracer.startSpan(spanName, {childOf: incomingSpanContext}) }
对于一个庞大的系统而言 业务中涉及的请求非常多 每个请求都手动埋点的工作量太大 一般这种方式也很难在公司进行推广 因此各类语言的自动埋点的方式开始蓬勃发展。自动埋点在Trace领域又叫做Trace Instrumentation 主要利用一些代理、装饰器、代码注入、AOP等技术 在请求处理之前产生Span 在请求处理完成后保存Span并自动发送到Trace服务端。
下述是一个常见的服务架构 Service A和Service B都是HTTP的服务实现 网络通信使用ServiceMesh进行流量管理 HTTP请求都会经过HTTP框架进行处理 然后提交到Dispatcher模块 该模块会根据不同的URL转发到对应的Hander进行处理。这一架构中 可以自动埋点的地方有3个
ServiceMesh层 所有的HTTP请求在处理的时候都进行埋点HTTP Framework 在HTTP请求接收、处理的过程中埋点Dispatcher 在转发的时候进行埋点一般而言 自动埋点也可以在多层同时进行 这样可以获取到每层对于性能的消耗是多少 对整体架构的性能开销有个更准确的理解。在生产上绝大部分情况都是使用自动埋点 对于有些自动埋点不能覆盖的场景 会用手动埋点的方式进行补全。例如某些语言不支持自动埋点、某个请求内部处理逻辑复杂需要手动创建子Span分成多个阶段...
自动埋点
手动埋点
工作量
低
高
支持的场景
少
全面
Trace完整度
低
高
性能开销
较高
低
我们知道Trace由Span组成 Span表示了当前某个调用的结果以及“父子”关系 而当某个Service的某个调用积累一定数量的时候 我们就可以分析出这个Service、调用的一些关键指标 访问次数(QPS)、延迟、错误率等。而这些通常也代表着我们的服务是否正常 因此通常情况下Trace不仅仅用来去查看某个请求是否有问题 更多的时候会用来监控服务是否正常。
基于Trace的监控不是从聚合指标而来 而是从每个调用来去计算出相应的访问次数、延迟、错误率 从原始数据计算的一个优点是可以较为准确的统计出PXX延迟 而PXX延迟也是反应用户对于我们业务真实体验的一个重要指标。因为通常情况下 平均延迟只能说明服务的情况 而不代表所有的客户访问都是如此的延迟 如果有一小部分的客户访问延迟很高 整体的平均延迟不会增加很多 但是这部分客户对于产品的体验会下降很多。
因此我们会更加关心P90、P95、P99之类的延迟指标 也就是按延迟正序排列 位于90%、95%、99%分位数的延迟大小。这部分延迟如果比平均延迟大非常多 那说明我们的服务在某些场景下对部分用户的体验非常不好 而这种情况下就需要去看这部分高延迟的指标具体耗时在哪个阶段 并进行针对性解决。
Dependency作为Trace的核心功能 是分析系统架构的利器 通过大数据工程 一般使用流计算、批量计算 分析所有上报的Span信息 将其中公共的关系提取、聚合 然后保存成一张DAG图。通常Dependency都只是从服务、调用维度进行计算 主要是因为这种计算的资源消耗比较少 毕竟服务、调用的组合比较少。
而实际场景中 我们希望知道在某个时间段、某一个进程、某一组容器的依赖关系 这就需要针对Span的Resource信息进行提取计算 组合关系会提升1-2个数量级 而计算复杂度和资源消耗也会随之提升。但带来的好处非常明显 我们能够知道更加细粒度的依赖关系 也更容易找出问题所在的机器、进程。
同时 在Dependency分析中 不仅仅只是计算DAG图的关系 而且还可以计算每个父子关系 也就是DAG图的边 的统计信息 包括调用次数、错误率、延迟等。因此在查看Dependency的时候 还可以看到某个节点调用其他服务的统计信息 更加有利于问题排查。
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信息等支持过滤。
7. Trace自定义分析如果把Trace的自定义过滤功能比作是千里眼 则Trace的自定义分析功能就是显微镜。Trace自定义过滤从茫茫的数据中发现感兴趣的一部分Trace数据 而自定义分析对这部分Trace数据进行详细的排查 找出其中有问题的那一部分。这里的分析主要利用统计学相关的技术 按照不同的维度组合去分析 而这些维度包括上述的任一Resource和Attribute信息 从中去发现异常的维度。
8. Trace自动化分析上述的自定义分析主要是靠人工 统计学 这种方式在数据维度不多的情况下还可以胜任 但如果要分析的数据维度超过3个时 纯粹的手工分析已经很难去把每个组合都尝试一遍。例如某个支付类型的调用成功率出现了下降 这个调用有地域、设备版本号、运营商、会员类型、支付类型5个维度信息 手动来做的话需要按照5个不同的维度去一一尝试 找到其中某个有明显分界的维度 再保存这个维度的信息 继续向其他4个维度进行尝试 最坏的情况下需要5*4*3*2*1次的手动分析才能找到问题的组合。而这个还是在问题只是由一个组合影响 如果有多个组合综合产生的结果 手动分析会收到多个结果的影响而更加复杂。
因此这时候我们就需要用算力和算法去做自动化的分析 利用算力从海量的组合中去一一分析 结合算法进行有效的剪枝 最终快速的得到造成调用错误率提升、延迟升高的维度组合。
9. 可观察性数据关联Trace可做的事情很多 但并不是万能的 Trace更多的是应用的关系数据以及从这些数据提取出的应用健康度 延迟、错误率、QPS等 数据。对于问题的根因分析还缺少一些关键的信息 包括与之关联的基础设施健康信息 例如Pod/主机核心指标、异常事件、内核报错等 以及应用的详细错误日志。这些通常情况下叫做Metrics、Logs数据。
为了能够让Trace更好的关联上述的其他数据 Trace中的Span必须包含对应的主机名、容器名、服务名等信息 也就是OpenTelemetry中的Resource信息。而且Trace方案需要提供快速跳转并查询对应数据的能力。
10. 自动根因定位当我们能够将Trace关联到Logs和Metrics时 就能够“顺藤摸瓜”找到问题的根本原因 无论是某台机器硬件故障 机器内核日志定位 、资源饱和 指标数据定位 、应用错误 应用报错日志 ...
这些问题的排查相比纯粹的Trace分析会更加复杂 需要与更多的系统交互 需要去查看更多的数据 因此所花费的时间也更久。而故障发生时 1分钟的损失也是难以接受的 因此我们需要更快的去发现这些问题 这时AIOps中的自动根因定位就派上了用场 利用Trace内部的“父子”关联关系以及Resource与Logs、Metrics的关联关系自动“顺藤摸瓜”去排查问题的根因所在 大大节省问题排查的时间 能够让问题的根因定位从小时/分钟级降低到秒级。
随着云原生、微服务技术的普及 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
根据调查,随着用户对计算能力、存储和网络容量的需求增长,服务器需求比经济不...
根据TrendForce的最新调查,自2020年初以来,COVID-19流感大流行加速了世界各地...
人头马君度(Rmy Cointreau)的历史非常重要,这家酒业公司以将最好的酒陈化100年...
本文中的五个步骤有助于您掌握转型的总体需求,并有助于您处理一些真正重要的事...
在VMworld 2020,VMware宣布与NVIDIA进行全面合作,共同推出新一代的混合云架构...
时间真快呀!转眼又至周一。让我们卯足干劲继续前行,先来看看上周有哪些不容错...
在疫情的影响下,人们的工作和生活方式在过去的一年发生了前所未有的变化。为了...
2020年11月26日深圳潮数科技于石家庄成功召开数据安全 新时代新基建信息应用之基...
【51CTO.com快译】数字化转型使应用程序领导人必须找到有效的方法来更新改造遗留...
2020年以来,由疫情停工减产所导致的缺芯困局影响着全球汽车发展,而本以为2021...