Contents
sleuth zipkin elk学习笔记
转载来源: sleuth zipkin elk学习笔记
sleuth 学习笔记
一、链路追踪
1.1 分布式环境下链路追踪
Timing信息
调用链路中的调用信息,包括 调用时间,哪个方法,
定位链路
整个链路会生成一个tracId 通过这个id在日志系统中能查询到上下游的整个链路调用过程
信息的收集和展示
报表
1.2 sleuth 功能
1.3 调用链路追踪模型

- Trace: 从头到尾贯穿整个流程,我们叫他TraceId 一次调用不管中间经历多少节点,都保持不变。
- Span :代表一个节点或者叫工作单元。通过一个唯一标识( SpanId,每个节点生成一个 )来标记它的开始、具体过程和结束来统计调用时间,除此之外,我们还可以获取如事件的名称。请求信息等元数据
- Annotation :用它记录一段时间内的事件,内部使用的重要注释。一个span可以有多个Annotation,包含一下几种:
- cs Client Sent: 客户端发送一个请求
- cr Client Received : 客户端接受了一个服务端发来的请求
- ss Server Sent: 服务端发送一个Response 给客户端
- sr Server Receive: 服务端接收了来自客户端的调用
这个信息是如何在链路间传递的?
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){
info("我是SleuthServerA,我收到信息:{}",msg);
log.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) {
run(ZipKinServerApp.class,args);
SpringApplication.
} }
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/ 的截图

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页面看到自己的调用记录了
调用简单截图

四、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 页面

我这里 A 服务跟 B 服务配置不同。
可见 我们可以将单个信息传输的es 也可以将所有信息打包记录到es。但是 单个信息记录的话更适合查找。
发表回复