我们都知道, 微服务之间通过 feign 传递, 在复杂的微服务架构系统中, 几乎每一个前端请求都会形成一个复杂的分布式服务调用链路, 在每条链路中任何一个依赖服务出现延迟超时或者错误都有可能引起整个请求最后的失败. 当业务流程足够复杂时, 一个完整的 HTTP 请求调用链一般会经过多个微服务系统, 要通过日志来跟踪一整个调用链变得不再那么简单. 通过 sleuth 可以很方便的看出每个采集请求的耗时情况, 分析出哪些服务调用比较耗时, 当服务调用的耗时随着请求量的增大而增大时, 可以针对业务做一些优化措施. 所以我们可以通过我们可以通过 Spring Cloud Sleuth 来解决这个问题. 这里我们将演示如何通过 Spring Cloud Sleuth 来追踪这个过程, 并借助 Zipkin 以图形化界面的方式展示. 展示之前, 分别介绍一下 rabbitmq,sleuth,zinkip.
rabbitmq
RabbitMQ 是实现了高级消息队列协议 (AMQP) 的开源消息代理软件(亦称面向消息的中间件).RabbitMQ 服务器是用 Erlang 语言编写的, 而群集和故障转移是构建在开放电信平台框架上的. 所有主要的编程语言均有与代理接口通讯的客户端库.
sleuth 和 zinkip
sleuth 是 spring cloud 的组成部分之一, 为 springcloud 应用实现了一种分布式追踪解决方案, 其兼容了 zinkip,HTrace 和 log-based 追踪
Zipkin 是一款开源的分布式实时数据追踪系统(Distributed Tracking System), 基于 Google Dapper 的论文设计而来, 由 Twitter 公司开发贡献. 其主要功能是聚集来自各个异构系统的实时监控数据, 用来追踪微服务架构下的系统延时问题. Zipkin 的用户界面可以呈现一幅关联图表, 以显示有多少被追踪的请求通过了每一层应用. Zipkin 以 Trace 结构表示对一次请求的追踪, 又把每个 Trace 拆分为若干个有依赖关系的 Span. 在微服务架构中, 一次用户请求可能会由后台若干个服务负责处理, 那么每个处理请求的服务就可以理解为一个 Span(可以包括 API 服务, 缓存服务, 数据库服务以及报表服务等). 当然这个服务也可能继续请求其他的服务, 因此 Span 是一个树形结构, 以体现服务之间的调用关系. Zipkin 的用户界面除了可以查看 Span 的依赖关系之外, 还以瀑布图的形式显示了每个 Span 的耗时情况, 可以一目了然的看到各个服务的性能状况.
sleuth 中的一些术语
Span: 基本工作单元, 例如, 在一个新建的 span 中发送一个 RPC 等同于发送一个回应请求给 RPC,span 通过一个 64 位 ID 唯一标识, trace 以另一个 64 位 ID 表示, span 还有其他数据信息, 比如摘要, 时间戳事件, 关键值注释(tags),span 的 ID, 以及进度 ID(通常是 IP 地址) ,span 在不断的启动和停止, 同时记录了时间信息, 当你创建了一个 span, 你必须在未来的某个时刻停止它.
Trace: 一系列 spans 组成的一个树状结构, 例如, 如果你正在跑一个分布式工程, 你可能需要创建一个 trace.
Annotation: 用来及时记录一个事件的存在, 一些核心 annotations 用来定义一个请求的开始和结束
cs - Client Sent - 客户端发起一个请求, 这个 annotion 描述了这个 span 的开始
sr - Server Received - 服务端获得请求并准备开始处理它, 如果将其 sr 减去 cs 时间戳便可得到网络延迟
ss - Server Sent - 注解表明请求处理的完成(当请求返回客户端), 如果 ss 减去 sr 时间戳便可得到服务端需要的处理请求时间
cr - Client Received - 表明 span 的结束, 客户端成功接收到服务端的回复, 如果 cr 减去 cs 时间戳便可得到客户端从服务端获取回复的所有所需时间
接下来就开始搭建
这里 cloud 版本用的 Greenwich.SR1,boot 使用的是 2.1.6
1. 在 pom.xml 中 引入 sleuth 依赖
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-sleuth</artifactId>
- </dependency>
2. 模拟两个日志 这两个服务之间通过 feign 调用, 由 test 调用 system, 这里本来有一个注册中心, 这里就不在演示了
test 模块
- @Slf4j
- @RestController
- public class TestController {
- @Autowired
- private IHelloService helloService;
- @GetMapping("hello")
- public String hello(String name) {
- log.info("Feign 调用 system 的 / hello 服务");
- return this.helloService.hello(name);
- }
- }
在 test 模块的 service 包下创建 IHelloService
- @FeignClient(value = "system",contextId = "helloServiceClient")
- public interface IHelloService {
- @GetMapping("hello")
- String hello(@RequestParam("name") String name);
- }
system 模块
- @Slf4j
- @RestController
- public class TestController {
- @GetMapping("hello")
- public String hello(String name) {
- log.info("/hello 服务被调用");
- return "hello" + name;
- }
- }
3. 访问接口 localhost:8202/test/hello?name=sleuth: 会出现两个我们自定义的日志
启动的时候查看 test 模块产生的
2019-08-23 14:22:51.774 INFO [test,72bb0469bee07104,72bb0469bee07104,false] 22728 --- [nio-8202-exec-1] c.m.f.s.test.controller.TestController : Feign 调用 system 的 / hello 服务
启动的时候查看 system 模块产生的
2019-08-23 14:22:52.469 INFO [system,72bb0469bee07104,43597a6edded6f2e,false] 812 --- [nio-8201-exec-2] c.m.f.s.s.controller.TestController : /hello 服务被调用
可以看到, 日志里出现了 [Test,72bb0469bee07104,72bb0469bee07104,false] 信息, 这些信息由 Spring Cloud Sleuth 生成, 用于跟踪微服务请求链路. 这些信息包含了 4 个部分的值, 它们的含义如下:
system 微服务的名称, 与 spring.application.name 对应;
72bb0469bee07104 称为 Trace ID, 在一条完整的请求链路中, 这个值是固定的. 观察上面的日志即可证实这一点;
43597a6edded6f2e 称为 Span ID, 它表示一个基本的工作单元;
false 表示是否要将该信息输出到 Zipkin 等服务中来收集和展示, 这里我们还没有集成 Zipkin, 所以为 false.
下面我们来整合 Zipkin
在整合 Zipkin 之前, 我们需要先搭建 RabbitMQ.RabbitMQ 用于收集 Sleuth 提供的追踪信息, 然后 Zipkin Server 从 RabbitMQ 里获取, 这样可以提升性能.
在安装 RabbitMQ 之前, 需要先安装 Erlang/OTP, 下载地址为: http://www.erlang.org/downloads/, 下载 exe 文件安装即可.
安装完毕后, 下载 RabbitMQ, 下载地址为 :
http://www.rabbitmq.com/install-windows.html, 下载 exe 文件安装即可.
安装完 RabbitMQ 之后, 我们到 RabbitMQ 安装目录的 sbin 下执行如下命令
rabbitmq-plugins enable rabbitmq_management
然后在浏览器中输入 http://localhost:15672, 默认用户名和密码都是 guest, 登录后可看到:
点击 Admin Tab 页面, 新增一个用户:
用户名为 febs, 密码为 123456, 角色为管理员. 新添加的用户还是 No access 状态, 需要进一步对该用户进行授权后, 方可以远程通过该用户名访问. 点击该新增用户名. 进入授权页面, 点击 Set permission 按钮, 进行用户授权操作.
安装好 RabbitMQ 后, 我们开始整合 Zipkin. 在较低版本的 Spring Cloud 中, 我们可以自己搭建 Zipkin Server, 现在我们只能使用官方搭建好的 Zipkin Server, 地址为: https://github.com/openzipkin/zipkin
在 cmd 窗口下运行下面这条命令(Windows 下没有 curl 环境的话, 可以在 Git bash 中运行这条命令), 下载 zipkin.jar:
curl -sSL https://zipkin.io/quickstart.sh | bash -s
如果下载速度极慢, 可以复制链接到迅雷下载中下载, 下载后重命名为 zipkin.jar 即可.
zipkin 支持将追踪信息保存到 MySQL 数据库, 所以在运行 zipkin.jar 之前, 我们先准备好相关库表, SQL 脚本地址为:
https://github.com/openzipkin/zipkin/blob/master/zipkin-storage/mysql-v1/src/main/resources/mysql.sql.
库表准备好后, 运行下面这条命令启动 zipkin.jar:
java -jar zipkin.jar --server.port=8402 --zipkin.storage.type=MySQL --zipkin.storage.MySQL.db=febs_cloud_base --zipkin.storage.MySQL.username=root --zipkin.storage.MySQL.password=123456 --zipkin.storage.MySQL.host=localhost --zipkin.storage.MySQL.port=3306 --zipkin.collector.rabbitmq.addresses=localhost:5672 --zipkin.collector.rabbitmq.username=febs --zipkin.collector.rabbitmq.password=123456
上面命令指定了数据库链接和 RabbitMQ 链接信息. 更多可选配置可以解压 zipkin.jar, 查看 zipkin\BOOT-INF\classes 路径下的 zipkin-server-shared.YAML 配置类源码.
启动好 zipkin.jar 后, 在对应模块的 pom 里引入如下依赖:
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-zipkin</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.amqp</groupId>
- <artifactId>spring-rabbit</artifactId>
- </dependency>
修改对应模块的 application.YAML
- spring:
- zipkin:
- sender:
- type: rabbit
- sleuth:
- sampler:
- probability: 1
- rabbitmq:
- host: localhost
- port: 5672
- username: febs
- password: 123456
spring.zipkin.sender.type 指定了使用 RabbitMQ 收集追踪信息;
spring.sleuth.sampler.probability 默认值为 0.1, 即采样率才 1/10, 发送 10 笔请求只有一笔会被采集. 为了测试方便, 我们可以将它设置为 1, 即 100% 采样;
spring.rabbitmq 用于配置 RabbitMQ 连接信息, 你可能会问, 为什么刚刚 RabbitMQ 端口是 15672, 这里却配置为 5672, 是不是写错了呢? 其实不是, 15672 是 RabbitMQ 的管理页面端口, 5672 是 AMPQ 端口.
添加好配置后, 启动 system 和 test 模块, 发送一笔 localhost:8202/test/hello?name = 夏天请求后, 使用浏览器访问 http://localhost:8402/zipkin / 链接, 然后点击图中所示
查看依赖关系:
查看数据表, 看是否存储了信息:
公众号: 良许 Linux
有收获? 希望老铁们来个三连击, 给更多的人看到这篇文章
来源: https://www.cnblogs.com/yychuyu/p/13324532.html