前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【进阶之路】分布式项目中的链路追踪

【进阶之路】分布式项目中的链路追踪

作者头像
南橘
发布2021-04-02 10:56:03
5160
发布2021-04-02 10:56:03
举报
文章被收录于专栏:进阶之路

.markdown-body{word-break:break-word;line-height:1.75;font-weight:400;font-size:15px;overflow-x:hidden;color:#333}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{line-height:1.5;margin-top:35px;margin-bottom:10px;padding-bottom:5px}.markdown-body h1{font-size:30px;margin-bottom:5px}.markdown-body h2{padding-bottom:12px;font-size:24px;border-bottom:1px solid #ececec}.markdown-body h3{font-size:18px;padding-bottom:0}.markdown-body h4{font-size:16px}.markdown-body h5{font-size:15px}.markdown-body h6{margin-top:5px}.markdown-body p{line-height:inherit;margin-top:22px;margin-bottom:22px}.markdown-body img{max-width:100%}.markdown-body hr{border:none;border-top:1px solid #ddd;margin-top:32px;margin-bottom:32px}.markdown-body code{word-break:break-word;border-radius:2px;overflow-x:auto;background-color:#fff5f5;color:#ff502c;font-size:.87em;padding:.065em .4em}.markdown-body code,.markdown-body pre{font-family:Menlo,Monaco,Consolas,Courier New,monospace}.markdown-body pre{overflow:auto;position:relative;line-height:1.75}.markdown-body pre>code{font-size:12px;padding:15px 12px;margin:0;word-break:normal;display:block;overflow-x:auto;color:#333;background:#f8f8f8}.markdown-body a{text-decoration:none;color:#0269c8;border-bottom:1px solid #d1e9ff}.markdown-body a:active,.markdown-body a:hover{color:#275b8c}.markdown-body table{display:inline-block!important;font-size:12px;width:auto;max-width:100%;overflow:auto;border:1px solid #f6f6f6}.markdown-body thead{background:#f6f6f6;color:#000;text-align:left}.markdown-body tr:nth-child(2n){background-color:#fcfcfc}.markdown-body td,.markdown-body th{padding:12px 7px;line-height:24px}.markdown-body td{min-width:120px}.markdown-body blockquote{color:#666;padding:1px 23px;margin:22px 0;border-left:4px solid #cbcbcb;background-color:#f8f8f8}.markdown-body blockquote:after{display:block;content:""}.markdown-body blockquote>p{margin:10px 0}.markdown-body ol,.markdown-body ul{padding-left:28px}.markdown-body ol li,.markdown-body ul li{margin-bottom:0;list-style:inherit}.markdown-body ol li .task-list-item,.markdown-body ul li .task-list-item{list-style:none}.markdown-body ol li .task-list-item ol,.markdown-body ol li .task-list-item ul,.markdown-body ul li .task-list-item ol,.markdown-body ul li .task-list-item ul{margin-top:0}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:3px}.markdown-body ol li{padding-left:6px}.markdown-body .contains-task-list{padding-left:0}.markdown-body .task-list-item{list-style:none}@media (max-width:720px){.markdown-body h1{font-size:24px}.markdown-body h2{font-size:20px}.markdown-body h3{font-size:18px}}

在单体服务的架构中,所有的服务,组件都在一台机器上,如果需要监控服务的异常与耗时,往往是比较简单的。我们可以使用 AOP 在调用具体的业务逻辑前后分别打印一下时间即可计算出整体的调用时间。在问题追踪的时候,也可以在关键节点打印日志。

但是在微服务架构里就不同了,一次请求会涉及到多个模块与系统,往往需要多台机器的相互协作才能完成。而一系列的请求,不仅会涉及到串联并联、还有同步异步之分。这个时候,如果依然采取单体架构中服务监控的方式,那么确定这个请求背后调用了哪些服务,哪些模块,哪些节点及调用的先后顺序,调用的耗时,或者追踪调用中出现的问题甚至会让开发人员当场去世。于是乎,我们马上就会想到链路追踪。

链路追踪:通过在程序内打点记录日志的方式,记录每次请求的调用链路信息。特点是数据精准、细致,适合查看某一次请求的调用链路,一般用于查看某些响应较慢的接口瓶颈。

要实现服务追踪,我们有三点问题需要解决:

  • 1、埋点并收集服务调用的上下文数据
  • 2、对收集到的数据进行分析、实时处理
  • 3、数据链路的可视化展示

通过分布式追踪系统能很好地定位如下请求的每条具体请求链路,从而轻易地实现请求链路追踪:

那么,有没有一种规范能让大家都很好的进行链路追踪系统的开发呢?

一、分布式调用链规范OpenTracing

为了解决不同的分布式追踪系统 API 不兼容的问题,诞生了 OpenTracing 规范,OpenTracing 是一个轻量级的标准化层,它位于应用程序/类库和追踪或日志分析程序之间。

1、OpenTracing是什么?

Opentracing是分布式链路追踪的一种规范标准,具有平台无关的特性,开发者只需修改少量的配置代码,就可以在符合Opentracing标准的链路追踪系统之间自由切换

被跟踪的服务只需要调用Opentracing接口,就可以被任何实现这套接口的跟踪后台(比如Zipkin, Jaeger等等)支持,而作为一个跟踪后台,只要实现了个这套接口,就可以跟踪到任何调用这套接口的服务。同时,Opentracing对进程间跟踪数据传递与追踪的最小独立单位Span进行了标准化

2、OpenTracing的数据结构

  • 1、Span

Span是一条追踪链路中的基本组成要素,也是最小独立单位。一个span表示一个独立的工作单元,比如可以表示一次函数调用,一次http请求等等。

span中包含以下信息:

  • 服务名称(调用请求的名字)
  • 服务的开始时间和结束时间
  • K/V形式的Tags
  • K/V形式的截断日志Logs
  • SpanContext(span上下文信息,其中包含 Trace ID 和 Span ID)
  • References:该span对一个或多个span的引用(通过引用SpanContext来获取)。
  • 2、Trace

一个完整请求链路,每个调用链由多个 Span 组成。

  • 3、SpanContext

Trace 的全局上下文信息, 如里面有包含着traceId。

大家可以看我这张图来了解数据结构,一次请求的完整请求完整就是一个Trace, 显然对于这个请求来说,必须要有一个全局标识来标识这一个请求TraceId,每一次调用就称为一个 Span每一次调用都要带上全局的TraceId和自身的SpanId, 这样才可把全局 TraceId 与每个调用关联起来。

3、OpenTracing的实现

了解到OpenTracing的数据结构之后。我们首先要收集服务Tacre的数据。

与单体服务中采用埋点的方式不同,现在主流的zipkin和SkyWalking采用了不同的方法收集服务链路的数据:

  • zipkin :拦截请求,发送(HTTP,MQ)数据至zipkin服务,需要的话可以持久化到数据库。
  • SkyWalking:使用 agent的形式去接入业务系统,这样就不需要在业务系统里添加任何的日志代码,也能记录到对应的调用数据库。

收集到的数据的内容如下图所示:

如果对每个请求调用都采集,那毫无疑问数据量会非常大。对于已经上线的服务而言,每一次请求的情况都是差不多的(如果出现异常报错当然另说)。其实没有必要对每个请求都采集,我们可以设置采样频率,只采样部分数据,SkyWalking中就默认设置了3秒只采样三次。这样的频率其实足够我们分析性能了(小声哔哔:其实大多数业务根本没有那么多的请求)。同时,为了保证全局一致性,上游服务采样了(SpanContext有说明),那么下游服务一定也需要采样,不然很有可能出现不一致的情况。

得到这些数据以后,对链路数据进行可视化展示就能实现服务追踪了。

二、zipkin实现OpenTracing规范

Zipkin是一款开源的分布式实时数据追踪系统,基于Google Dapper的论文设计而来,由Twitter公司开发贡献,它的架构图如下:

但是光有Zipkin还不够,Spring Cloud为我们提供了Sleuth这个组件,它可以为服务之间调用提供错误补货,耗时分析和链路追踪

Spring Cloud Sleuth可以结合Zipkin,将信息发送到Zipkin,利用Zipkin的存储来存储信息,利用Zipkin Ui来展示数据(Sleuth 默认采用 Http 方式将 span 传输给 Zipkin)。

1、简单搭建zipkin项目

基于springboot来搭建zipkin还是比较简单的事情,在生成模块的时候已经有了完整的脚手架,只需要在maven(或者gradle等任何仓库)放上对应的依赖就行。

代码语言:javascript
复制
在zipkin项目中引入依赖

        
	
    		org.springframework.cloud
    		spring-cloud-starter-sleuth
	
	
    		org.springframework.cloud
    		spring-cloud-starter-zipkin
	
         
        
            org.springframework.amqp
            spring-rabbit
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    
    
 在service与client项目中也需要引入zipkin依赖
   
        
            org.springframework.cloud
            spring-cloud-starter-zipkin
        

为什么选择 RabbitMQ 消息中间件发送 span 信息

sleuth 默认采用 http 通信方式,将数据传给 zipkin 作页面渲染,但是 http 传输过程中如果由于不可抗因素导致 http 通信中断,那么此次通信的数据将会丢失。但是使用RabbitMQ的话,消息队列可以积压千万级别的消息,下次重连之后依然可以可以继续消费。随着线程增多,并发量提升之后,RabbitMQ 异步发送数据明显更具有优势。同时,RabbitMQ 支持消息、队列持久化,可以通过消息状态落库、重回队列、镜像队列等技术手段保证其高可用。具体可以参考RabbitMQ原理

除了依赖方面,在yaml中,zipkin这样配置

代码语言:javascript
复制
server:
  port: 9411
spring:
  application:
    name: zipkin-server
  main:
    allow-bean-definition-overriding: true
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
management:
  metrics:
    web:
      server:
        auto-time-requests: false
        
其它服务端中加入zipkin的配置
spring:
  sleuth:
    sampler:
      probability: 1.0
  zipkin:
    base-url: http://localhost:9411

在使用 Spring Boot 2.x 版本后,官方就不推荐自行定制编译了,让我们直接使用编译好的 jar 包。所以我们在使用@EnableZipkinServer或@EnableZipkinStreamServer注解的时候要注意搭配好springboot的版本。

代码语言:javascript
复制
@SpringBootApplication
@EnableEurekaClient
@EnableZipkinServer
public class ZipkinServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ZipkinServerApplication.class, args);
    }

}

2、zipkin UI

搭建完毕以后,我们可以登录 http://localhost:9411/zipkin/ 地址进入zipkin的主页:

点击Find Traces就能看到较为简洁的显示Span的个数以及调用总时延。

我们进入一个完整的调用链后访问其中的一个节点得到以下数据:

然后在Dependencies的选项中能看到调用链路的图,当然,因为测试的原因,并没有建立很复杂的调用链路。

从这一块我们能够感知到,springcloud对zipkin的集成非常友好,不用另外启动什么jar包,可以直接集成在springcloud的环境中,这也是我选择用zipkin作为展示的原因。

三、链路追踪系统中的常见问题

1、TraceId的全局唯一

要保证TraceId的全局唯一就可以了,这里我们可以参考 SOFATrace 中的设计,通过 8 位的 IP 地址和 13 位的时间戳,以及四位的自增序列,加上本身进程的 PID 号,这样组成的字符串就可以保证全局唯一了。

IP地址

生产ID的时间

自增序列

进程PID

8位

13位

4位

可变序列

0ad1348f

1403169275002

1003

56696

2、如何优化数据采集过程

举个例子,可以使用消息中间件优化:安装rabbitmaq,修改zipkin服务器的启动方式,从rabbit拉取消息。

修改客户端以rabbitmq的形式向mq发送消息(在需要收集日志的微服务中添加依赖,修改配置)

3、采样率设置

实际上 Trace 的采样率一直是个头疼的问题,设置太低可能有些接口采集不到有效的信息,设置得太高又会造成成本过高的问题。在 Jaeger 中提供了动态采样率的功能,这样可以保证同一个服务中,低 QPS 的接口可以被有效采集,而高 QPS 的接口有较低的采样率。

四、其他链路追踪系统

Zipkin是Twitter开源的调用链分析工具,目前基于springcloud sleuth得到了广泛的使用,特点是轻量,使用部署简单。

除此之外还有:

  • SkyWalking 本土开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多种插件,UI功能较强,接入端无代码侵入。目前已加入Apache孵化器。
  • Pinpoint 韩国人开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多种插件,UI功能强大,接入端无代码侵入。
  • CAT 大众点评开源的基于编码和配置的调用链分析,应用监控分析,日志采集,监控报警等一系列的监控平台工具。

类别

Zipkin

SkyWalking

Pinpoint

CAT

实现方式

拦截请求,发送(HTTP,mq)数据至zipkin服务

java探针,字节码增强

java探针,字节码增强

代码埋点(拦截器,注解,过滤器等)

接入方式

基于linkerd或者sleuth方式,引入配置即可

javaagent字节码

javaagent字节码

代码埋点(拦截器,注解,过滤器等)

代码侵入

http,MQ

gRPC

thrift

http/tcp

数据存储

ES,mysql,Cassandra,内存

ES,H2

Hbase

mysql,hdfs

颗粒度

接口级

方法级

方法级

代码级

社区活跃度

至于开发选型的问题,大家可以根据自己的产品实际选择适合的链路追踪系统,可以参考这篇知乎文章监控系统比较 Skywalking Pinpoint Cat zipkin

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、分布式调用链规范OpenTracing
    • 1、OpenTracing是什么?
      • 2、OpenTracing的数据结构
        • 3、OpenTracing的实现
        • 二、zipkin实现OpenTracing规范
          • 1、简单搭建zipkin项目
            • 2、zipkin UI
            • 三、链路追踪系统中的常见问题
              • 1、TraceId的全局唯一
                • 2、如何优化数据采集过程
                  • 3、采样率设置
                  • 四、其他链路追踪系统
                  相关产品与服务
                  消息队列 TDMQ
                  消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档