使用 Zipkin 对 Spring Cloud 应用程序进行服务跟踪分析
本文简要介绍如何使用 Zipkin 对 Spring Cloud 应用进行服务分析。在实际应用中,Zipkin 可以与压力测试工具结合使用,以分析系统在高压下的可用性和性能。
想象一下这样的场景:如果你的微服务逐渐增长,服务之间的依赖关系也变得越来越复杂,你将如何分析它们之间的调用关系和相互影响?
服务追踪分析
由微服务组成的应用程序通过服务划分问题域,并通过 REST API 连接服务来完成操作。一次入口服务调用可能需要多个后端服务的协调。链接上的任何调用超时或错误都可能导致前端请求失败。服务调用链会越来越长,形成一个树状的调用链。
尽管与原文不符,但我认为这应该是“服务调用”…一次服务调用可能需要多个后端服务的协调。一次服务调用可能需要多个后端服务的协调。
随着服务的增多,对调用链的分析也将变得越来越细致。假设你负责下面的系统,其中的每一个小点都是一个微服务。微服务之间的调用关系构成了复杂的网络。
微服务之间的调用关系构成了复杂的网络
针对面向服务的应用程序的整体链式追踪问题,Google 发表了 Dapper 论文,介绍了他们是如何进行服务追踪分析的。其基本思想是为服务调用请求和响应添加一个 ID,以指示上下游请求的关系。利用这些信息,可以可视化地分析服务调用链和服务之间的依赖关系。
Spring Cloud Sleuth 和 Zipkin
与 Dapper 对应的开源实现是 Zipkin。它支持 JavaScript、Python、Java、Scala、Ruby、C# 和 Go 等多种语言。其中,Java 支持不同的数据库。
在本例中,我们准备开发两个基于 Spring Cloud 的应用程序,并使用 Spring Cloud Sleuth 与 Zipkin 集成。Spring Cloud Sleuth 是 Zipkin 的一种封装,它自动化了 span 和 trace 信息的生成、HTTP 请求的访问以及将收集到的信息发送到 Zipkin Server。
这是 Spring Cloud Sleuth 的概念图。
服务 REST 调用
本示例中有两个演示服务:tracedemo,充当前端服务,接收用户请求;tracebackend,充当后端服务。tracedemo 通过 HTTP 协议调用后端服务。
@RequestMapping("/") public String callHome(){ LOG.log(Level.INFO, "calling trace demo backend"); return restTemplate.getForObject("hLmpk344008ttp://backend:8090", String.class); }
使用 RestTemplate 进行 HTTP 请求调用
tracedemo 应用程序通过 RestTemplate
调用后端 tracebackend 服务。注意:tracedemo 地址在 URL 中指定为 backend。
@RequestMapping("/") public String callHome(){ LOG.log(Level.INFO, "calling trace demo backend"); return restTemplate.getForObject("http://backend:8090", String.class); }
后端服务响应 HTTP 请求,输出日志显示返回了经典的“hello world”。
@RequestMapping("/") public String home(){ LOG.log(Level.INFO, "trace demo backend is being called"); return "Hello World."; }
引入 Sleuth 和 Zipkin 依赖包
我们可以看到,这是两个 Spring 应用程序通过 RestTemplate
进行的一次典型访问。那么,其中哪一个在 HTTP 请求中注入了追踪信息并将信息发送到 Zipkin Server 呢?答案在于这两个应用程序加载的 JAR 包。
本例使用 Gradle 构建应用程序。Sleuth 和 Zipkin 相关的 JAR 包在 build.gradle 中加载。
dependencies { compile('org.springframework.cloud:spring-cloud-starter-sleuth') compile('org.springframework.cloud:spring-cloud-sleuth-zipkin') testCompile('org.springframework.boot:spring-boot-starter-test') }
在 Spring 应用程序检测到 Java 依赖包中的 Sleuth 和 Zipkin 后,它会在 RestTemplate
调用期间自动将追踪信息注入 HTTP 请求,并将信息发送到 Zipkin Server。
那么,我们可以在哪里指定 Zipkin Server 的地址呢?答案是:在 application.properties 中。
spring.zipkin.base-url=http://zipkin-server:9411
注意:Zipkin Server 的地址是:zipkin-server。
构建 Docker 镜像
为这两个服务创建两个相同的 Dockerfile 来生成 Docker 镜像。
FROM java:8-jre-alpine RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/' /etc/apk/repositories VOLUME /tmp ADD build/libs/*.jar app.jar RUN sh -c 'touch /app.jar' ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
构建 Docker 镜像的步骤如下:
cd tracedemo ./gradlew build docker build -t zipkin-demo-frontend . cd ../tracebackend ./gradlew build docker build -t zipkin-demo-backend .
镜像准备就绪后,使用 `docker push` 命令将镜像上传到你的镜像仓库。
Zipkin Server
通过注解声明创建 Zipkin。
在 build.gradle 中引入 Zipkin 依赖包。
dependencies { compile('org.springframework.boot:spring-boot-starter') compile('io.zipkin.java:zipkin-server') runtime('io.zipkin.java:zipkin-autoconfigure-ui') testCompile('org.springframework.boot:spring-boot-starter-test') }
在主程序类中添加 @EnableZipkinServer
注解。
@SpringBootApplication @EnableZipkinServer public class ZipkinApplication { public static void main(String[] args) { SpringApplication.run(ZipkinApplication.class, args); } }
在 application.properties 中将端口指定为 9411。
server.port=9411
构建 Docker 镜像
这里的 Dockerfile 与前面两个服务相同,因此不再赘述。
在阿里云 Docker 上部署
创建 docker-compose.yml 文件,内容如下:
version: "2" services: zipkin-server: image: registry.cn-hangzhou.aliyuncs.com/jingshanlb/zipkin-demo-server labels: aliyun.routing.port_9411: http://zipkin restart: always frontend: image: registry.cn-hangzhou.aliyuncs.com/jingshanlb/zipkin-demo-frontend labels: aliyun.routing.port_8080: http://frontend links: - zipkin-server - backend restart: always backend: image: registry.cn-hangzhou.aliyuncs.com/jingshanlb/zipkin-demo-backend links: - zipkin-server restart: always
创建应用程序
使用阿里云 Docker 上的编排模板,访问 Zipkin 端点,你将看到服务分析的效果。
访问前端应用程序三次,页面显示三次服务调用。
点击任意 trace,你将看到请求链接上不同 span 的持续时间。
进入 Dependencies 页面,你将看到服务之间的依赖关系。
从这个过程可以看出,Zipkin 与 Spring Cloud 的集成是成功的。服务追踪分析的可视化也非常直观。
值得注意的是,在生产环境中,你还需要为 Zipkin 配置数据库。此处不再详述。
本文的演示代码可以在这里找到:https://github.com/binblee/zipkin-demo。