sleuth zipkin elk学习笔记

sleuth zipkin elk学习笔记

转载来源: sleuth zipkin elk学习笔记

sleuth 学习笔记

一、链路追踪

1.1 分布式环境下链路追踪

Timing信息

调用链路中的调用信息,包括 调用时间,哪个方法,

定位链路

整个链路会生成一个tracId 通过这个id在日志系统中能查询到上下游的整个链路调用过程

信息的收集和展示

报表

1.2 sleuth 功能

1.3 调用链路追踪模型

sleuth模型
  • Trace: 从头到尾贯穿整个流程,我们叫他TraceId 一次调用不管中间经历多少节点,都保持不变。
  • Span :代表一个节点或者叫工作单元。通过一个唯一标识( SpanId,每个节点生成一个 )来标记它的开始、具体过程和结束来统计调用时间,除此之外,我们还可以获取如事件的名称。请求信息等元数据
  • Annotation :用它记录一段时间内的事件,内部使用的重要注释。一个span可以有多个Annotation,包含一下几种:
    • cs Client Sent: 客户端发送一个请求
    • cr Client Received : 客户端接受了一个服务端发来的请求
    • ss Server Sent: 服务端发送一个Response 给客户端
    • sr Server Receive: 服务端接收了来自客户端的调用

这个信息是如何在链路间传递的?

sleuth 正是通过过滤器修改 header 中的属性来传递信息的,属性如下:

sleuth在header中的属性

二、代码演示

一个 sleuth-server-a —> sleuth-server-b —> sleuth-server-c

2.1 以sleuth-server-a为例相关依赖配置

依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--eureka 模块-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <!--sleuth-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-sleuth</artifactId>
    </dependency>

    <!--feign 依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

配置

server:
  port: 8901

spring:
  application:
    name: sleuth-server-a
eureka:
  client:
    register-with-eureka: true # 是否将自己注册到eureka上 不配置默认是true
    fetch-registry: true # 是否从eureka服务上拉取拉取 服务信息 不配置默认是true
    serviceUrl:
      defaultZone: http://localhost:7005/eureka/ # 注册到eureka服务上。

测试类

API

@FeignClient("sleuth-server-b")
public interface FeignApiA {

    @GetMapping("/sendMsgB")
    String sendMsg(@RequestParam("msg") String msg);

}
@RestController
@Slf4j
public class TestController {
    private final FeignApiA feignApiA;

    public TestController(FeignApiA feignApiA) {
        this.feignApiA = feignApiA;
    }

    @GetMapping("sendMsg")
    public String sendMsg(@RequestParam("msg") String msg){

        log.info("我是SleuthServerA,我收到信息:{}",msg);
        return feignApiA.sendMsg(msg);

    }

代码比较简单,bc 就不挨个创建了。

2.2 三台机器日志分析

2021-11-02 21:09:42.176  INFO [sleuth-server-a,8424c5a64eba998d,8424c5a64eba998d] 3708 --- [nio-8901-exec-1] c.z.sleuth.a.controller.TestController   : 我是SleuthServerA,我收到信息:你好

## 重要信息列举
INFO [sleuth-server-a,8424c5a64eba998d,8424c5a64eba998d] 3708 
INFO [sleuth-server-b,8424c5a64eba998d,953c369b5cbc1530] 12004
INFO [sleuth-server-c,8424c5a64eba998d,f8043aa027fdfb4b] 16764

三台机器的日志中,8424c5a64eba998d 为 tracId 贯穿整个调用,后面的那个为 spanId每个机器中有一个

三、sleuth的好搭档zipkin

zipkin 主要用来分析调用情况,便于排查问题。若是查看具体的日志可以借助elk来实现。

3.1 主要有四部分组成

  • Collector :是zipkin server 的守护进程,主要用来验证客户端发来的链路数据,并在存储中建立索引
  • Stronger :zpikin 支持 es跟mysql作为日志链路收集存储
  • Search Engin:提供json API接口来查询日志信息
  • Dashboard :日志监控

3.2 构建一个zipkin-server

版本 spring-boot 2.1.5.RELEASE

zipkin 2.8.4

3.2.1 依赖

<dependencies>
    <!--eureka 模块-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <!--新版本的zipkin脱离了这种构架方式直接提供了一种启动jar包的方式-->
    <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-server</artifactId>
        <version>2.8.4</version>
    </dependency>
    <!--控制台,前台查询页面-->
    <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-ui</artifactId>
        <version>2.8.4</version>
    </dependency>
</dependencies>

3.2.2 配置

server:
  port: 8904

spring:
  application:
    name: zipkin-server
  main:
    allow-bean-definition-overriding: true # 同名类允许覆盖
management:
  metrics:
    web:
      server:
        request:
          autotime:
            enabled: false
eureka:
  client:
    register-with-eureka: true # 是否将自己注册到eureka上 不配置默认是true
    fetch-registry: true # 是否从eureka服务上拉取拉取 服务信息 不配置默认是true
    serviceUrl:
      defaultZone: http://localhost:7005/eureka/ # 注册到eureka服务上。

3.2.3 启动类

@SpringBootApplication
@EnableDiscoveryClient
@EnableZipkinServer
public class ZipKinServerApp {

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

3.2.4 测试

启动访问http://127.0.0.1:8904/zipkin/就可以看到zipkin控制台页面

3.2.5 总结

2021年11月3日 我在使用的时候发现 我使用的高版本的spring boot 2.5.1出现不兼容问题,去官网发现新版本的到2.23.4了,集成方式也不是上述的情况了,而是下载然后运行

  • 通过 docker

    docker run -d -p 9411:9411 openzipkin/zipkin
  • 通过jar包

    curl -sSL https://zipkin.io/quickstart.sh | bash -sjava -jar zipkin.jar
  • 或者下载源代码

    # get the latest sourcegit clone https://github.com/openzipkin/zipkincd zipkin# Build the server and also make its dependencies./mvnw -DskipTests --also-make -pl zipkin-server clean install# Run the serverjava -jar ./zipkin-server/target/zipkin-server-*exec.jar

下面是运行后访问 http://127.0.0.1:9411/zipkin/ 的截图

zipkin2.23.4页面

3.3 整合 sleuth 跟 zipkin

在上面 的调用服务中引入

3.3.1 依赖

<!--zipkin-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>

3.3.2配置

server:
  port: 8903

spring:
  application:
    name: sleuth-server-c
  sleuth:
    sampler:
      probability: 1 # 采样率 100% 0.8 采样率 80%
  zipkin:
    base-url: http://127.0.0.1:9411 # zipkin-server 的地址
eureka:
  client:
    register-with-eureka: true # 是否将自己注册到eureka上 不配置默认是true
    fetch-registry: true # 是否从eureka服务上拉取拉取 服务信息 不配置默认是true
    serviceUrl:
      defaultZone: http://localhost:7005/eureka/ # 注册到eureka服务上。

3.3.3总结

主要是通过 zipkin.base-url=http://127.0.0.1:9411来发送日志调用记录的。

他不是日志收集工具,是记录服务与服务之间的调用关系。

此时就可以在zipkin页面看到自己的调用记录了

调用简单截图

zipkin的调用关系

四、sleuth 集成 elk日志采集

sleuth 主要是 给系统打标记,方便链路追踪,elk的使用可以完全脱离sleuth ,但是如果需要在打印的日志中记录 traceId spanId 可以使用sleuth 进行标记。

4.1 安装elk

这里通过docker 安装的

1. 下载镜像(时间很久,耐心要足):
docker pull sebp/elk

2. 创建Docker容器(只用在第一次使用的时候才创建)
docker run -p 5601:5601 -p 9200:9200 -p 5044:5044 -e ES_MIN_MEM=128m  -e ES_MAX_MEM=1024m -it --name elk sebp/elk

3. 进入docker容器:
docker exec -it elk /bin/bash

4. 修改配置文件
配置文件的位置:/etc/logstash/conf.d/02-beats-input.conf
将其中的内容都删掉,替换成下面的配置
input {
    tcp {
        port => 5044
        codec => json_lines

    }

}
output{
    elasticsearch {
    hosts => ["localhost:9200"]

    }

}

5. 重启docker容器(大概等5-10分钟,等待服务重启)
docker restart elk

6. 访问Kibana
http://localhost:5601/

4.2 配置

主要借助logstash 组件

依赖:

<!-- logstash-->
<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>5.2</version>
</dependency>

logback-spring.xml 配置

主要使用的 LogstashTcpSocketAppender

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!--引入颜色,打印的日志带颜色,使用%clr() 包裹着日志-->
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <springProperty scope="context" name="springAppName"
                    source="spring.application.name" />
    <!--设置存储路径变量-->
    <property name="LOG_HOME" value="./log"/>
    <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
        <Property name="LOG_PATTERN" value="%d{yyyy-MM-dd hh:mm:ss.SSS} | %-5level | ${springAppName:-} | %X{X-B3-TraceId:-} | %X{X-B3-SpanId:-} | %clr(${LOG_LEVEL_PATTERN:-%5p})|%clr(${PID:- }){magenta}| [%t] |%logger{50} | %L | : %msg%n"/>

    <!--控制台输出appender-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!--设置输出格式-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>${LOG_PATTERN}</pattern>
            <!--设置编码-->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <!-- 为logstash输出的JSON格式的Appender -->
    <appender name="logstash"
              class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>192.168.0.109:5044</destination>
        <!-- 日志输出编码 -->
        <encoder
                class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp>
                    <timeZone>UTC</timeZone>
                </timestamp>
                <pattern>
                    <pattern>
                        {
                        "datetime":"%d{yyyy-MM-dd hh:mm:ss.SSS}",
                        "level": "%-5level",
                        "serviceName": "${springAppName:-}",
                        "trace": "%X{X-B3-TraceId:-}",
                        "span": "%X{X-B3-SpanId:-}",
                        "code":"${LOG_LEVEL_PATTERN:-%5p}",
                        "pid": "${PID:-}",
                        "thread": "%thread",
                        "class": "%logger{50}",
                        "message": "%message"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
    </appender>

    <!--指定基础的日志输出级别-->
    <root level="INFO">
        <!--appender将会添加到这个loger-->
        <appender-ref ref="console"/>
        <appender-ref ref="logstash" />
    </root>
</configuration>

<destination>192.168.0.109:5044</destination>指定logstash 的地址,剩下的都是elk自动去给你同步到es 在kibanna 展示。

一切就绪,开始调用

日志打印。

日志

访问Kibana,进入 discover 页面

kibana

我这里 A 服务跟 B 服务配置不同。

可见 我们可以将单个信息传输的es 也可以将所有信息打包记录到es。但是 单个信息记录的话更适合查找。


评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注