Sleuth微服务链路追踪整合ELK和zipkin

简介: Sleuth微服务链路追踪整合ELK和zipkin

1 分布式计算八大误区

网络可靠。

延迟为零。

带宽无限。

网络绝对安全。

网络拓扑不会改变。

必须有一名管理员。

传输成本为零。

网络同质化。(操作系统,协议)

2 链路追踪的必要性

如果能跟踪每个请求,中间请求经过哪些微服务,请求耗时,网络延迟,业务逻辑耗时等。我们就能更好地分析系统瓶颈、解决系统问题。因此链路跟踪很重要。


我们自己思考解决方案:在调用前后加时间戳。捕获异常。


链路追踪目的:解决错综复杂的服务调用中链路的查看。排查慢服务。


市面上链路追踪产品,大部分基于google的Dapper论文。

zipkin,twitter开源的。是严格按照谷歌的Dapper论文来的。
pinpoint 韩国的 Naver公司的。
Cat 美团点评的
EagleEye 淘宝的

3 链路追踪要考虑的几个问题

  1. 探针的性能消耗。尽量不影响 服务本尊。
  2. 易用。开发可以很快接入,别浪费太多精力。
  3. 数据分析。要实时分析。维度足够。

4 Sleuth简介

Sleuth是Spring cloud的分布式跟踪解决方案。


span(跨度),基本工作单元。一次链路调用,创建一个span,


span用一个64位id唯一标识。包括:id,描述,时间戳事件,spanId,span父id。


span被启动和停止时,记录了时间信息,初始化span叫:root span,它的span id和trace id相等。


trace(跟踪),一组共享“root span”的span组成的树状结构 称为 trace,trace也有一个64位ID,trace中所有span共享一个trace id。类似于一颗 span 树。


annotation(标签),annotation用来记录事件的存在,其中,核心annotation用来定义请求的开始和结束。


CS(Client Send客户端发起请求)。客户端发起请求描述了span开始。

SR(Server Received服务端接到请求)。服务端获得请求并准备处理它。SR-CS=网络延迟。

SS(Server Send服务器端处理完成,并将结果发送给客户端)。表示服务器完成请求处理,响应客户端时。SS-SR=服务器处理请求的时间。

CR(Client Received 客户端接受服务端信息)。span结束的标识。客户端接收到服务器的响应。CR-CS=客户端发出请求到服务器响应的总时间。

其实数据结构是一颗树,从root span 开始。

5 快速入门

5.1 Sleuth入门搭建

api_gateway_server 工程模块基础上扩展

5.1.1 引入坐标

<!--sleuth链路追踪-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

5.1.2 yml配置

各个微服务的yml配置文件都要加入日志

logging:
  level:
    root: info
    org.springframework.web.servlet.DispatcherServlet: DEBUG
    org.springframework.cloud.sleuth: DEBUG
  • 每个微服务都需要添加如上的配置

5.1.3 访问测试

  • 启动微服务并调用,可以在控制台观察到sleuth的日志输出

其中7c8d741c36af2723是TraceId,后面的是SpanId,依次调用有一个全局的TraceId,将调用链路串起来。仔细分析每个微服务的日志,不难看出请求的具体过程。

查看日志文件并不是一个很好的方法,当微服务越来越多日志文件也会越来越多,通过Zipkin可以将日

志聚合,并进行可视化展示和全文检索

各个服务的控制台都可以看到日志的输出

6 项目整合Zipkin

6.1 docker 安装 zipkin

docker run -d -p 9411:9411 openzipkin/zipkin

6.2 在pom中添加依赖

 <!--zipkin 依赖也同时包含了 sleuth,可以省略 sleuth 的引用-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zipkin</artifactId>
    </dependency>

6.3 在application.yml添加如下配置

spring:
  zipkin:
    base-url: http://192.168.2.190:9411/  # zipkin 服务器的地址
    discovery-client-enabled: false # 关闭服务发现,否则 Spring Cloud 会把 zipkin 的 url 当做服务名称
    sender:
      type: web # 设置使用 http 的方式传输数据
  sleuth:
    sampler:
      probability: 1  # 设置抽样采集率为 100% ,默认为 0.1 ,即 10%

6.4 本地测试

启动项目,所有功能都跑一遍,然后访问 zipkin 服务器地址,显示如下:

7 sleuth+elk聚合日志

sleuth配置

  • 在微服务项目引入下列依赖
 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
  • 配置文件application.yml增加
logging:
  level:
    root: INFO
    org.springframework.web.servlet.DispatcherServlet: DEBUG
    org.springframework.cloud.sleuth: DEBUG
  • 依次启动hello项目helloworld项目,在浏览器输入http://localhost:8020/message后两个项目的控制台输出如下日志

helloworld日志


hello 日志.png


其中a7c81616d25c1a88是TraceId,后面跟着的是SpanId,依次调用有一个全局的TraceId,将调用链路串起来。


查看日志文件并不是一个很好的方法,当微服务越来越多日志文件也会越来越多,通过ELK可以将日志聚合,并进行可视化展示和全文检索。

sleuth配合elk使用


ELK是一款日志分析系统,它是Logstash+ElasticSearch+Kibana的技术组合,它可以通过logstash收集各个微服务日志,并通过Kibana进行可视化展示,而且还可以对大量日志信息通过ElasticSearch进行全文检索。


5f889695836480fff3621e987985a1d1.png

ELK.png

操作步骤:

  • 安装ELK,我使用了docker安装了ELK,具体安装步骤可参考这篇文章:

Docker部署es和kibana

区别是在启动logstash时,指定了日志来源路径

/opt/logstash/bin/logstash -e 
'input { file { codec => json path => "/opt/build/*.json" } } 
output { elasticsearch { hosts => ["localhost"] } }'
  • 项目添加依赖
      <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
            <version>4.9</version>
        </dependency>
  • 在src/java/resources目录下新建logback-spring.xml,配置如下内容
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <springProperty scope="context"
                    name="springAppName"
                    source="spring.application.name"/>
    <property name="LOG_FILE"
              value="${BUILD_FOLDER:-build}/${springAppName}"/>
    <property name="CONSOLE_LOG_PATTERN"
              value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p})
              %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan}
              %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    <!-- 控制台输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>
    <!-- 按照每天生成日志文件 -->
    <appender name="filelog"  class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>7</MaxHistory>
        </rollingPolicy>
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>
    <!-- 使用json格式保存日志文件 -->
    <appender name="jsonlog"  class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}.json</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_FILE}.json.%d{yyyy-MM-dd}.gz</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>7</MaxHistory>
        </rollingPolicy>
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp>
                    <timeZone>UTC</timeZone>
                </timestamp>
                <pattern>
                    <pattern>
                        {
                        "severity": "%level",
                        "service": "${springAppName:-}",
                        "trace": "%X{X-B3-TraceId:-}",
                        "span": "%X{X-B3-SpanId:-}",
                        "parent": "%X{X-B3-ParentSpanId:-}",
                        "exportable": "%X{X-Span-Export:-}",
                        "pid": "${PID:-}",
                        "thread": "%thread",
                        "class": "%logger{40}",
                        "rest": "%message"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>
    <root level="INFO">
        <appender-ref ref="console"/>
        <appender-ref ref="jsonlog"/>
        <appender-ref ref="filelog"/>
    </root>
</configuration>

因为上面的日志文件用到spring.application.name,所以需要项目名称的配置挪到bootstrap.yml。


测试结果,在浏览器输入http://localhost:8020/message发起几次调用后,打开http://localhost:5601后看到上述的Kibana页面,说明可以正常使用ELK查询,分析跟踪日志。

相关实践学习
分布式链路追踪Skywalking
Skywalking是一个基于分布式跟踪的应用程序性能监控系统,用于从服务和云原生等基础设施中收集、分析、聚合以及可视化数据,提供了一种简便的方式来清晰地观测分布式系统,具有分布式追踪、性能指标分析、应用和服务依赖分析等功能。 分布式追踪系统发展很快,种类繁多,给我们带来很大的方便。但在数据采集过程中,有时需要侵入用户代码,并且不同系统的 API 并不兼容,这就导致了如果希望切换追踪系统,往往会带来较大改动。OpenTracing为了解决不同的分布式追踪系统 API 不兼容的问题,诞生了 OpenTracing 规范。OpenTracing 是一个轻量级的标准化层,它位于应用程序/类库和追踪或日志分析程序之间。Skywalking基于OpenTracing规范开发,具有性能好,支持多语言探针,无侵入性等优势,可以帮助我们准确快速的定位到线上故障和性能瓶颈。 在本套课程中,我们将全面的讲解Skywalking相关的知识。从APM系统、分布式调用链等基础概念的学习加深对Skywalking的理解,从0开始搭建一套完整的Skywalking环境,学会对各类应用进行监控,学习Skywalking常用插件。Skywalking原理章节中,将会对Skywalking使用的agent探针技术进行深度剖析,除此之外还会对OpenTracing规范作整体上的介绍。通过对本套课程的学习,不止能学会如何使用Skywalking,还将对其底层原理和分布式架构有更深的理解。本课程由黑马程序员提供。
目录
相关文章
|
3月前
|
Dubbo Java 应用服务中间件
微服务框架(十六)Spring Boot及Dubbo zipkin 链路追踪组件埋点
此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。 本文第一部分为调用链、OpenTracing、Zipkin和Jeager的简述;第二部分为Spring Boot及Dubbo zipkin 链路追踪组件埋点
|
5月前
|
监控 微服务
微服务技术系列教程(28) - SpringCloud- 分布式服务跟踪Sleuth
微服务技术系列教程(28) - SpringCloud- 分布式服务跟踪Sleuth
23 0
|
1月前
|
消息中间件 SpringCloudAlibaba Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(八)Config服务配置+bus消息总线+stream消息驱动+Sleuth链路追踪
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(八)Config服务配置+bus消息总线+stream消息驱动+Sleuth链路追踪
785 0
|
5月前
|
存储 监控 Java
微服务技术系列教程(42)- SpringCloud -Sleuth与Zipkin服务链路
微服务技术系列教程(42)- SpringCloud -Sleuth与Zipkin服务链路
68 0
|
4月前
|
存储 前端开发 算法
微服务线上问题排查困难?不知道问题出在哪一环?那是你还不会分布式链路追踪
微服务线上问题排查困难?不知道问题出在哪一环?那是你还不会分布式链路追踪
|
5月前
|
消息中间件 Java API
微服务技术系列教程(43)- SpringCloud -Zipkin环境集成
微服务技术系列教程(43)- SpringCloud -Zipkin环境集成
50 0
|
6月前
|
中间件 Go API
Go语言微服务框架 - 9.分布式链路追踪-OpenTracing的初步引入
我们从API层到数据库层的链路已经打通,简单的CRUD功能已经可以快速实现。 随着模块的增加,我们会越发感受到系统的复杂性,开始关注系统的可维护性。这时,有个名词会进入我们的视野:**分布式链路追踪**
54 0
|
7天前
|
敏捷开发 监控 数据管理
构建高效微服务架构的五大关键策略
【4月更文挑战第20天】在当今软件开发领域,微服务架构已经成为一种流行的设计模式,它允许开发团队以灵活、可扩展的方式构建应用程序。本文将探讨构建高效微服务架构的五大关键策略,包括服务划分、通信机制、数据管理、安全性考虑以及监控与日志。这些策略对于确保系统的可靠性、可维护性和性能至关重要。
|
7天前
|
消息中间件 监控 持续交付
构建高效微服务架构:后端开发的进阶之路
【4月更文挑战第20天】 随着现代软件开发的复杂性日益增加,传统的单体应用已难以满足快速迭代和灵活部署的需求。微服务架构作为一种新兴的分布式系统设计方式,以其独立部署、易于扩展和维护的特点,成为解决这一问题的关键。本文将深入探讨微服务的核心概念、设计原则以及在后端开发实践中如何构建一个高效的微服务架构。我们将从服务划分、通信机制、数据一致性、服务发现与注册等方面入手,提供一系列实用的策略和建议,帮助开发者优化后端系统的性能和可维护性。
|
2天前
|
监控 测试技术 持续交付
探索现代微服务架构的最佳实践
【4月更文挑战第25天】 随着软件开发领域不断演进,微服务架构已成为设计灵活、可扩展且高度可维护系统的首选方案。本文将深入探讨构建和部署微服务时的关键最佳实践,涵盖从服务划分原则到持续集成/持续部署(CI/CD)的流程,再到监控与日志记录的策略。我们的目标是为开发者提供一套实用的指南,帮助他们在构建未来的应用程序时做出明智的架构选择,并确保这些系统能够快速响应市场和技术的变化。