Spring Cloud 系列之 Sleuth 链路追踪(二)
本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Sleuth 链路追踪(一)
本篇文章讲解 Sleuth 基于 Zipkin 存储链路追踪数据至 MySQL,Elasticsearch 以及使用 MQ 存储链路追踪数据至 MySQL,Elasticsearch。
存储追踪数据
Zipkin Server 默认存储追踪数据至内存中,这种方式并不适合生产环境,一旦 Server 关闭重启或者服务崩溃,就会导致历史数据消失。Zipkin 支持修改存储策略使用其他存储组件,支持 MySQL,Elasticsearch 等。
MySQL
数据库脚本
打开 MySQL 数据库,创建 zipkin 库,执行以下 SQL 脚本。
--
-- Copyright 2015-2019 The OpenZipkin Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software distributed under the License
-- is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions and limitations under
-- the License.
--
CREATE TABLE IF NOT EXISTS zipkin_spans (
`trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
`trace_id` BIGINT NOT NULL,
`id` BIGINT NOT NULL,
`name` VARCHAR(255) NOT NULL,
`remote_service_name` VARCHAR(255),
`parent_id` BIGINT,
`debug` BIT(1),
`start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',
`duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query',
PRIMARY KEY (`trace_id_high`, `trace_id`, `id`)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds';
ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and getSpanNames';
ALTER TABLE zipkin_spans ADD INDEX(`remote_service_name`) COMMENT 'for getTraces and getRemoteServiceNames';
ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces ordering and range';
CREATE TABLE IF NOT EXISTS zipkin_annotations (
`trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
`trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id',
`span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id',
`a_key` VARCHAR(255) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1',
`a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB',
`a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation',
`a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',
`endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null',
`endpoint_ipv6` BINARY(16) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',
`endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null',
`endpoint_service_name` VARCHAR(255) COMMENT 'Null when Binary/Annotation.endpoint is null'
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds';
ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames';
ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for getTraces and autocomplete values';
ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces and autocomplete values';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job';
CREATE TABLE IF NOT EXISTS zipkin_dependencies (
`day` DATE NOT NULL,
`parent` VARCHAR(255) NOT NULL,
`child` VARCHAR(255) NOT NULL,
`call_count` BIGINT,
`error_count` BIGINT,
PRIMARY KEY (`day`, `parent`, `child`)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
部署 Zipkin 服务端
添加启动参数,重新部署服务端:
java -jar zipkin-server-2.20.1-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=localhost --MYSQL_TCP_PORT=3306 --MYSQL_USER=root --MYSQL_PASS=root --MYSQL_DB=zipkin
测试
访问:http://localhost:9000/order-service/order/1 查看数据库结果如下:
在 MySQL 模式下,每次启动服务端时,服务端会从数据库加载链路信息展示至 Web 界面。
RabbitMQ
点击链接观看:基于 MQ 并存储链路信息至 MySQL 视频(获取更多请关注公众号「哈喽沃德先生」)
之前的课程中我们已经学习过 RabbitMQ 的详细使用,这里不再过多赘述,直接开启使用即可。
启动 RabbitMQ 服务器
开启虚拟机,通过以下命令启动 RabbitMQ 服务端。
systemctl start rabbitmq-server.service
访问:http://192.168.10.101:15672/ 使用默认用户名和密码 guest
查看队列,此时无任何队列。
部署 Zipkin 服务端
添加启动参数,重新部署服务端:
java -jar zipkin-server-2.20.1-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=localhost --MYSQL_TCP_PORT=3306 --MYSQL_USER=root --MYSQL_PASS=root --MYSQL_DB=zipkin --RABBIT_ADDRESSES=192.168.10.101:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest --RABBIT_VIRTUAL_HOST=/ --RABBIT_QUEUE=zipkin
启动参数中包含 MySQL 和 RabbitMQ 的配置,实现基于 MQ 并存储链路信息至 MySQL,如下图:
查看队列
访问:http://192.168.10.101:15672/#/queues 可以看到已经创建好了 zipkin 队列。
客户端添加依赖
<!-- spring cloud zipkin 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<!-- 消息队列通用依赖 -->
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
</dependency>
客户端配置文件
spring:
zipkin:
base-url: http://localhost:9411/ # 服务端地址
sender:
type: rabbit
rabbitmq:
queue: zipkin # 队列名称
rabbitmq:
host: 192.168.10.101 # 服务器 IP
port: 5672 # 服务器端口
username: guest # 用户名
password: guest # 密码
virtual-host: / # 虚拟主机地址
listener:
direct:
retry:
enabled: true # 是否开启发布重试
max-attempts: 5 # 最大重试次数
initial-interval: 5000 # 重试间隔时间(单位毫秒)
simple:
retry:
enabled: true # 是否开启消费者重试
max-attempts: 5 # 最大重试次数
initial-interval: 5000 # 重试间隔时间(单位毫秒)
sleuth:
sampler:
probability: 1.0 # 收集数据百分比,默认 0.1(10%)
测试
先关闭 Zipkin 服务端,访问:http://localhost:9000/order-service/order/1 客户端已将链路追踪数据写入队列当中:
启动 Zipkin 服务端后,队列中消息被消费。
链路追踪数据被存储至 MySQL。
Elasticsearch
之前的课程中我们已经学习过 Elasticsearch 的详细使用,这里不再过多赘述,直接开启使用即可。
启动 Elasticsearch 集群
本文使用的 Elasticsearch 集群地址为:
- 192.168.10.101:9200
- 192.168.10.102:9200
- 192.168.10.103:9200
启动集群,访问:http://192.168.10.101:9200/_cluster/health?pretty 结果如下:
启动 head 插件,访问:http://192.168.10.101:9100/ 结果如下:
部署 Zipkin 服务端
添加启动参数,重新部署服务端:
java -jar zipkin-server-2.20.1-exec.jar --STORAGE_TYPE=elasticsearch --ES_HOSTS=http://192.168.10.101:9200/,http://192.168.10.102:9200/,http://192.168.10.103:9200/ --RABBIT_ADDRESSES=192.168.10.101:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest --RABBIT_QUEUE=zipkin
启动参数中包含 Elasticsearch 和 RabbitMQ 的配置,实现基于 MQ 并存储链路信息至 Elasticsearch。
查看索引库
访问:http://192.168.10.101:9100 可以看到已经创建好了 zipkin 索引库。
客户端添加依赖
<!-- spring cloud zipkin 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<!-- 消息队列通用依赖 -->
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
</dependency>
客户端配置文件
spring:
zipkin:
base-url: http://localhost:9411/ # 服务端地址
sender:
type: rabbit
rabbitmq:
queue: zipkin # 队列名称
rabbitmq:
host: 192.168.10.101 # 服务器 IP
port: 5672 # 服务器端口
username: guest # 用户名
password: guest # 密码
virtual-host: / # 虚拟主机地址
listener:
direct:
retry:
enabled: true # 是否开启发布重试
max-attempts: 5 # 最大重试次数
initial-interval: 5000 # 重试间隔时间(单位毫秒)
simple:
retry:
enabled: true # 是否开启消费者重试
max-attempts: 5 # 最大重试次数
initial-interval: 5000 # 重试间隔时间(单位毫秒)
sleuth:
sampler:
probability: 1.0 # 收集数据百分比,默认 0.1(10%)
测试
访问:http://localhost:9000/order-service/order/1 查看索引库结果如下:
下一篇我们讲解 Sleuth 如何使用 Elasticsearch、Logstash、Kibana 分析追踪数据,记得关注噢~
本文采用 知识共享「署名-非商业性使用-禁止演绎 4.0 国际」许可协议。
大家可以通过 分类 查看更多关于 Spring Cloud 的文章。
Spring Cloud 系列之 Sleuth 链路追踪(二)的更多相关文章
- Spring Cloud 系列之 Sleuth 链路追踪(三)
本篇文章为系列文章,未读前几集的同学请猛戳这里: Spring Cloud 系列之 Sleuth 链路追踪(一) Spring Cloud 系列之 Sleuth 链路追踪(二) 本篇文章讲解 Sleu ...
- Spring Cloud 系列之 Sleuth 链路追踪(一)
随着微服务架构的流行,服务按照不同的维度进行拆分,一次请求往往需要涉及到多个服务.互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发.可能使用不同的编程语言来实现.有可能布在了 ...
- Spring Cloud Alibaba(13)---Sleuth概述
Sleuth概述 前言 在微服务架构中,众多的微服务之间互相调用,如何清晰地记录服务的调用链路是一个需要解决的问题.同时,由于各种原因,跨进程的服务调用失败时,运维人员希望能够通过 查看日志和查看服务 ...
- Spring cloud系列十四 分布式链路监控Spring Cloud Sleuth
1. 概述 Spring Cloud Sleuth实现对Spring cloud 分布式链路监控 本文介绍了和Sleuth相关的内容,主要内容如下: Spring Cloud Sleuth中的重要术语 ...
- Spring Cloud系列(二) 介绍
Spring Cloud系列(一) 介绍 Spring Cloud是基于Spring Boot实现的微服务架构开发工具.它为微服务架构中涉及的配置管理.服务治理.断路器.智能路由.微代理.控制总线.全 ...
- Spring Cloud 系列之 Consul 注册中心(二)
本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Consul 注册中心(一) 本篇文章讲解 Consul 集群环境的搭建. Consul 集群 上图是一个简单的 Co ...
- Spring Cloud 系列之 Gateway 服务网关(二)
本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Gateway 服务网关(一) 本篇文章讲解 Gateway 网关的多种路由规则.动态路由规则(配合服务发现的路由规则 ...
- Spring Cloud 系列之 Stream 消息驱动(二)
本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Stream 消息驱动(一) 本篇文章讲解 Stream 如何实现消息分组和消息分区. 消息分组 如果有多个消息消费者 ...
- Spring Cloud 系列之 Config 配置中心(二)
本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Config 配置中心(一) 本篇文章讲解 Config 如何实现配置中心自动刷新. 配置中心自动刷新 点击链接观看: ...
随机推荐
- 在C#MVC三层项目中如何使用SprintNet
0.添加dll文件 1.首先在根目录下新建一个文件夹[Config],然后新建2两个xml文件. 1-1[controllers.xml]用来配置需要创建的对象 1-2[service.xml]用来配 ...
- 操作系统-IO与显示器
1. 让外设工作起来 只要给相应的控制器中的寄存器发一个指令 向设备控制器的寄存器写不就可以了吗? 需要查寄存器地址.内容的格式和语义.操作系统需要给用户提供一个简单视图---文件视图,这样方便 总的 ...
- SpringBoot 入门:项目属性配置
开发一个SpringBoot 项目,首当其冲,必然是配置项目 一.项目属性配置 1. SpringBoot自带了Tomcat服务器,通过使用项目配置文件来修改项目的配置,如图配置了部署在80端口,目录 ...
- Git Bash使用时有个end,无法进行其他操作
如图: 遇到这种情况,按下q即可回到$命令界面.
- Light of future-冲刺Day 7
目录 1.SCRUM部分: 每个成员进度 SCRUM 会议的照片 签入记录 代码运行截图 用户浏览界面 订单详情界面 管理员浏览界面 新增后台界面 2.PM 报告: 时间表 燃尽图 任务总量变化曲线 ...
- ansible七种武器和json
ansible七种武器和json • 第一种武器 – ansible 命令,用于执 ...
- Java中如何通过try优雅地释放资源?
时间紧迫,长话短说,今天,小明给大家同步一个知识点,使用try-with-resources来优雅地关闭资源. 1. 背景 其实,在JDK 7就已经引入了对try-with-resources的支持, ...
- PTA 6-1 单链表逆转
本题是一个非常经典的题目:单链表逆转. 这是链表结点的定义: typedef struct Node *PtrToNode; struct Node { ElementType Data; /* 存储 ...
- json文件操作
1.把字典或list转换成字符串方法 json.dumps() 2.把字符串转换成字典方法 json.loads() 3.indent 存储文件时每行加缩进数 4.ensere_asci 文件中有中文 ...
- 8.2 常见api:String类的使用
/* * String:字符串类 * 由多个字符组成的一串数据 * 字符串其本质是一个字符数组 * * 构造方法: * String(String original):把字符串数据封装成字符串对象 * ...