前言

最近项目需要做一些链路跟踪的需求,以前对zipkin + sleuth 有过了解,但没有自己动手搭建过,借这次的需求手动实践下,顺便写写博客,做做笔记

一、zipkin

1.1 简介

Zipkin是一个分布式跟踪系统,可以搜集服务上报的调用信息,包括http、mysql、redis、mongodb、dubbo等,然后进行相应的展示,上报信息通过traceId进行关联,每个调用就生成一个span,span中有parentId关联上一个span,具体的描述可以参考官网,官网总共没有多少模块,可以看看,github上也有相应的代码

1.2 结构

architecture-1

  • Reporter 是集成在服务中的,负责收集相应的信息
  • Transport 是将服务上报的信息传输给zipkin的通道,有http、Kafka、Scribe(facebook开源的日志系统)等
  • Collector负责收集服务上报的信息,Storage储存到相应的介质,如mysql、es等,api提供http接口返回json数据供UI展示

二、搭建zipkin

zipkin搭建直接用docker,存储用的es

2.1 elasticsearch
docker run -d -p 9200:9200 -p 9300:9300 elasticsearch:6.6.2
# 完成过后,需要进行容器修改跨域设置
docker exec -it 容器id /bin/bash
cd config
vim elasticsearch.yml
# vim 没有的话 需要安装下 apt-get update & apt-get install vim
# 加入下面两行
http.cors.enabled: true
http.cors.allow-origin: "*"
2.2 elasticsearch-head

为了方便查看建议安装head插件,5.0 之后的版本已经没有head plugin 了,我这边直接docker安装

docker run -p 9100:9100 mobz/elasticsearch-head:5
# 之后进行使用搜索的时候,会出现406的问题,需要进入head容器里面,修改_site/vendor.js 6886行 7574行,这两处改为
# application/json;charset=UTF-8
2.3 zipkin
docker run -d -p 9411:9411 -e STORAGE_TYPE=elasticsearch -e ES_HOSTS=http://真实ip:port openzipkin/zipkin
# --restart=always 这个随个人,可加可不加,加了docker重启,容器会自动重启

三、与springboot集成

我用的springboot的版本是 2.2.0.RELEASE

<!-- 引入zipkin 里面有sleuth -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
# 在application.properties 中进行配置 sleuth收集的粒度的参数可以自行查查
spring.zipkin.base-url=http://localhost:9411/
spring.sleuth.sampler.probability=1
spring.sleuth.web.client.enabled=true
3.1 mysql跟踪
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-mysql8</artifactId>
<version>5.9.0</version>
</dependency>
# 相应的修改application.properties中mysql的配置
spring.datasource.url=jdbc:mysql://ip:port/数据库?queryInterceptors=brave.mysql8.TracingQueryInterceptor&exceptionInterceptors=brave.mysql8.TracingExceptionInterceptor&zipkinServiceName=自己取名字

# 这样就已经集成了mysql的跟踪
3.3 dubbo跟踪
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-dubbo-rpc</artifactId>
<version>5.4.1</version>
<!-- 解决冲突用的 -->
<exclusions>
<exclusion>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave</artifactId>
</exclusion>
</exclusions>
</dependency>

dubbo的跟踪需要在resource项目建立 META-INFO.dubbo文件夹,然后新建com.alibaba.dubbo.rpc.Filter 文件,文件中写入

tracing=brave.dubbo.rpc.TracingFilter,然后在 application.properties 文件中配置tracing这个filter

spring.dubbo.consumer.filter=tracing
3.4 mongodb跟踪
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-mongodb</artifactId>
<version>5.12.4</version>
</dependency

mongodb的跟踪不能通过配置直接解决,需要给mongoClient添加commandListener

@Configuration
public class MongodbConfig {

@Bean
public MongoClientOptions mongoOptions() {
CommandListener listener = MongoDBTracing.create(Tracing.current())
.commandListener();
// MongoClientOptions 中可以自己设定相应的mongo配置参数
return MongoClientOptions.builder().addCommandListener(listener).build();
}
}
3.4 brave

上面这些能力都是brave提供的j各种 instrumentation java 库,相应的代码可以参考Github

四、展示

上面两部分完成过后,就还可以访问zipkinUI来,本机部署的话访问 http://localhost:9411,打开后会有相应的展示

相应的搜索条件有 servicename、spanname、tags等,选中一个可以展示详情

WechatIMG14

WechatIMG15

上图中第一个span是我通过置入过滤器直接嵌入的,并且给span打了特定的tag,logId

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class TraceFilter extends OncePerRequestFilter {

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Span logSpan = null;
try {
Tracer tracer = Tracing.currentTracer();
logSpan = tracer.newTrace().name("log")
.tag("logId", "输入自己想要的值")
.start();
tracer.withSpanInScope(logSpan);
filterChain.doFilter(request, response);
} finally {
if (logSpan != null) {
logSpan.finish(System.currentTimeMillis());
}
}
}
}

五、sleuth和zipkin的关系

Sleuth是收集收据的,zipkin是存储展示数据的