2018/07/02 Tracing with Spring Cloud Sleuth and Zipkin

在前边章节中,我们学习了如何使用 spring cloud 搭建微服务,随着服务越来越多,一旦服务出错,定位很难,所以我们就需要有一个能够快速直观的监控服务机制,本节要学习的 sleuth 就是这样一款分布式跟踪工具。

假如我们已经有 3 个服务,它们之间的调用关系为 service1 调用 service2 ,service2 调用 service3 。要使用 sleuth 来监控他们的调用链只需要加上 sleuth 的依赖。

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

之后我们就会在控制台看到有类似 [service1,84caca7a1662da40,84caca7a1662da40,false] 的日志,sleuth 对调用链的监控就是靠这个实现的。那么这些日志都是什么意思呢?这就涉及到 zipkin 的基本概念了。

  • traceId
    就是一个全局的跟踪 ID ,用来标识一条调用链。
  • spanId
    一个 span 可以看成是一次调用,spanId 就是这次调用的 ID 。
  • parentId
    上一次调用的 ID,用来将前后的请求串联起来。
  • cs(client send)
    客户端发起请求,在 span 开始的时候设置。
  • sr(server receive)
    服务端收到请求之后开始处理请求之前。sr 和 cs 的时间差就是网络延时。
  • ss(server send)
    服务端处理完成并返回给客户端。ss 和 sr 的时间差就是服务器处理的时长。
  • cr(client receive)
    客户端收到响应,在 span 结束的时候设置。cr 标识着一次请求完成。

了解了这些基本概念,再结合日志我们就可以搞清楚 sleuth 的处理过程了。

[serviceName,traceId,spanId,upload]
[service1,8412e2eebe56a8c0,8412e2eebe56a8c0,true]
[service2,8412e2eebe56a8c0,ced32b7682dfb002,true]
[service3,8412e2eebe56a8c0,fecfced41b92ee72,true]

当我们请求 service1 时,由于这是一个新的请求,所以首先会生成一个随机的 traceId 和 spanId 8412e2eebe56a8c0,parentId 为空,当 service1 调用下游的 service2 时,会生成一个新的 span 同时生成一个新的 spanId ced32b7682dfb002 ,但会使用相同的 traceId 8412e2eebe56a8c0 ,service1 的 spanId 8412e2eebe56a8c0 会作为 service2 的 parantId 。service2 调用 service3 处理逻辑也是一样的。Trace 的信息就会通过这样的方式从上游服务 service1 一直传递到下游服务 service3 ,直到整个调用链结束。

有了这些跟踪信息,在通过可视化的组建 zipkin 就可以直观的监控调用链的信息了。下面我们就来看看如何使用 zipkin 收集 sleuth 的日志信息。

首先在服务中加入依赖。

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

添加 zipkin 配置。

spring:
  zipkin:
    base-url: http://localhost:9411

然后启动一个 zipkin-server ,以 docker 为例。

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

访问 http://localhost:9411/zipkin/ 可以看到 zipkin-server 的界面。然后我们请求 service1 ,日志出现 [service1,249309b6a4120e9f,249309b6a4120e9f,false] 类似日志,最后一位表示是否采样,就是是否被 zipkin 收集,false 表示未收集,访问第 10 次就会输出一条 true 的日志(和采样率 spring.sleuth.sampler.probability 有关,默认是 10%),这时我们在 zipkin 中就能够查询到调用链的信息了。