集成sleuth_Spring Cloud Sleuth整合zipkin过程解析

article/2025/9/20 21:41:11

这篇文章主要介绍了Spring Cloud Sleuth整合zipkin过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

SpringCloud Sleuth 简介

Spring Cloud Sleuth为Spring Cloud实现了分布式跟踪解决方案。

Spring Cloud Sleuth借鉴了Dapper的术语。

Span:基本的工作单元。Span包括一个64位的唯一ID,一个64位trace码,描述信息,时间戳事件,key-value 注解(tags),span处理者的ID(通常为IP)。

Trace:一组Span形成的树形结构。

Annotation:用于及时记录存在的事件。常用的Annotation如下:

cs:客户端发送(client send) 客户端发起一个请求,表示span开始

sr:服务器接收(server received) 服务器接收到客户端的请求并开始处理,sr - cs 的时间为网络延迟

ss:服务器发送(server send) 服务器处理完请求准备返回数据给客户端。ss - sr 的时间表示服务器端处理请求花费的时间

cr:客户端接收(client received) 客户端接收到处理结果,表示span结束。 cr - cs 的时间表示客户端接收服务端数据的时间

下图展示了Span和Trace在系统中的联系

fbcaf518327ad845871f755a37927d70.png

Sleuth 默认采用 Http 方式将 span 传输给 Zipkin

在application.properties文件中指定

spring.zipkin.sender.type=web

使用 RabbitMQ 异步发送 span 信息

为什么选择 RabbitMQ 消息中间件发送 span 信息

sleuth 默认采用 http 通信方式,将数据传给 zipkin 作页面渲染,但是 http 传输过程中如果由于不可抗因素导致 http 通信中断,那么此次通信的数据将会丢失。而使用中间件的话,RabbitMQ 消息队列可以积压千万级别的消息,下次重连之后可以继续消费。

随着线程增多,并发量提升之后,RabbitMQ 异步发送数据明显更具有优势。

RabbitMQ 支持消息、队列持久化,可以通过消息状态落库、重回队列、镜像队列等技术手段保证其高可用。

示例

示例简介

示例包含sleuth-search、sleuth-cart、sleuth-order三个系统,用来模拟电商系统中下单的流程,用户可以搜索商品然后立即下单,也可以搜索多个商品后加入购物车,然后下单,调用情况即 search -> cart -> order,或 search -> order。

示例使用 RestTemplate 来完成三个系统间的 http 请求响应,请求方式也都遵循Restful风格。

版本说明

版本一定要对应好,一些低版本的SpringBoot无法兼容新版本的SpringCloud和zipkin

工具

版本

SpringBoot

2.1.6.RELEASE

SpringCloud

Greenwich.SR3

zipkin

2.16.2

项目结构

demo-cloudsleuth

|- sleuth-search

|- sleuth-cart

|- sleuth-order

pom.xml

导入依赖

org.springframework.boot

spring-boot-starter-parent

2.1.6.RELEASE

org.springframework.cloud

spring-cloud-dependencies

Greenwich.SR3

pom

import

org.springframework.cloud

spring-cloud-starter-zipkin

org.springframework.amqp

spring-rabbit

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

test

配置 RestTemplate,RestTemplate是SpringBoot提供的封装好的http工具类,可以帮助我们简化http的使用。

package com.anqi.cart.resttmplate;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.http.client.ClientHttpRequestFactory;

import org.springframework.http.client.SimpleClientHttpRequestFactory;

import org.springframework.web.client.RestTemplate;

@Configuration

public class RestTemplateConfig {

@Bean

public RestTemplate restTemplate(ClientHttpRequestFactory factory) {

return new RestTemplate(factory);

}

@Bean

public ClientHttpRequestFactory clientHttpRequestFactory() {

SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();

factory.setConnectTimeout(5000);

factory.setReadTimeout(5000);

return factory;

}

}

三个系统下的application.properties,端口分别是8081 8082 8083

#server.port=8081 server.port=8082

server.port=8083

server.servlet.context-path=/

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

spring.zipkin.service.name=sleuth-cart

#使用默认 http 方式收集 span 需要配置此项

#spring.zipkin.sender.type=web

#sleuth 使用 rabbitmq 来向 zipkin 发送数据

spring.zipkin.sender.type=rabbit

spring.rabbitmq.host=localhost

spring.rabbitmq.port=5672

spring.rabbitmq.username=guest

spring.rabbitmq.password=guest

#设置采样率默认为 0.1 注意之前的版本是percentage 新版本中更换为 probability

spring.sleuth.sampler.probability=1

三个系统下的RestTemplate的配置,用来简化 http 请求

package com.anqi.cart.resttmplate;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.http.client.ClientHttpRequestFactory;

import org.springframework.http.client.SimpleClientHttpRequestFactory;

import org.springframework.web.client.RestTemplate;

@Configuration

public class RestTemplateConfig {

@Bean

public RestTemplate restTemplate(ClientHttpRequestFactory factory) {

return new RestTemplate(factory);

}

@Bean

public ClientHttpRequestFactory clientHttpRequestFactory() {

SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();

factory.setConnectTimeout(5000);

factory.setReadTimeout(5000);

return factory;

}

}

@RequestMapping("cart")

@RestController

public class CartController {

@Autowired

RestTemplate restTemplate;

@Autowired

CartService cartService;

private static final String orderUrl = "http://localhost:8084/order/create";

@GetMapping("/add/{cartId}")

public String addToCart(@PathVariable("cartId") String cartId) {

cartService.addProductToCart(cartId, "小米8");

ResponseEntity res = restTemplate.getForEntity(orderUrl, String.class);

return res.getBody();

}

}

@RequestMapping("order")

@RestController

public class OrderController {

@GetMapping("/create")

public String creatOrder() {

System.out.println("create order");

return "create_order";

}

}

@RestController

public class SearchController {

@Autowired

RestTemplate restTemplate;

private static final String cartUrl = "http://localhost:8083/cart/add/1";

private static final String orderUrl = "http://localhost:8084/order/create";

@GetMapping("/search")

public String search() {

ResponseEntity cartRes = restTemplate.getForEntity(cartUrl, String.class);

ResponseEntity orderRes = restTemplate.getForEntity(orderUrl, String.class);

return "cart:" + cartRes.getBody() + "- order:" + orderRes.getBody();

}

}

运行结果分析

默认 http 传输 span 信息

启动Zipkin

java -jar zipkin-server-2.16.2-exec.jar

网页中手动访问

http://localhost:8082/search

我们访问zipkin站点查询调用情况

http://localhost:9411/zipkin/traces/94b954d843012ca9

可以从下图中完整清晰的看到三个系统的调用关系

38b804caa5d74eae59e69fbfcbec8ce9.png

下图为zipkin调用预览,我们请求四次http://localhost:8082/search来更直观的观察数据。在以下界面中,较为简洁的显示Span的个数以及调用总时延。

0b8ae82e08e0120783b0a7096a353cc6.png

我们进入一个完整的调用链后访问其中的一个节点得到以下数据。

2f49f8c4cb75ee2969def5e2f4d08e07.png

以下为一次全链路追踪的详细信息,包含7个span的所有信息,以上看到的页面展示均有以下数据加以渲染而成。

[

{

"traceId": "94b954d843012ca9",

"parentId": "bab70b1e69a5f3e3",

"id": "96387b33a823ca8f",

"kind": "SERVER",

"name": "get /order/create",

"timestamp": 1569060494069123,

"duration": 1161,

"localEndpoint": {

"serviceName": "sletuth-order",

"ipv4": "192.168.0.107"

},

"remoteEndpoint": {

"ipv4": "127.0.0.1",

"port": 49863

},

"tags": {

"http.method": "GET",

"http.path": "/order/create",

"mvc.controller.class": "OrderController",

"mvc.controller.method": "creatOrder"

},

"shared": true

},

{

"traceId": "94b954d843012ca9",

"parentId": "94b954d843012ca9",

"id": "90f7e5cfa89e0d80",

"kind": "SERVER",

"name": "get /order/create",

"timestamp": 1569060494076287,

"duration": 1296,

"localEndpoint": {

"serviceName": "sletuth-order",

"ipv4": "192.168.0.107"

},

"remoteEndpoint": {

"ipv4": "127.0.0.1",

"port": 49864

},

"tags": {

"http.method": "GET",

"http.path": "/order/create",

"mvc.controller.class": "OrderController",

"mvc.controller.method": "creatOrder"

},

"shared": true

},

{

"traceId": "94b954d843012ca9",

"parentId": "94b954d843012ca9",

"id": "bab70b1e69a5f3e3",

"kind": "CLIENT",

"name": "get",

"timestamp": 1569060494063693,

"duration": 10374,

"localEndpoint": {

"serviceName": "sleuth-search",

"ipv4": "192.168.0.107"

},

"tags": {

"http.method": "GET",

"http.path": "/cart/add/1"

}

},

{

"traceId": "94b954d843012ca9",

"parentId": "94b954d843012ca9",

"id": "90f7e5cfa89e0d80",

"kind": "CLIENT",

"name": "get",

"timestamp": 1569060494074966,

"duration": 2848,

"localEndpoint": {

"serviceName": "sleuth-search",

"ipv4": "192.168.0.107"

},

"tags": {

"http.method": "GET",

"http.path": "/order/create"

}

},

{

"traceId": "94b954d843012ca9",

"id": "94b954d843012ca9",

"kind": "SERVER",

"name": "get /search",

"timestamp": 1569060494062631,

"duration": 16332,

"localEndpoint": {

"serviceName": "sleuth-search",

"ipv4": "192.168.0.107"

},

"remoteEndpoint": {

"ipv6": "::1",

"port": 49859

},

"tags": {

"http.method": "GET",

"http.path": "/search",

"mvc.controller.class": "SearchController",

"mvc.controller.method": "search"

}

},

{

"traceId": "94b954d843012ca9",

"parentId": "bab70b1e69a5f3e3",

"id": "96387b33a823ca8f",

"kind": "CLIENT",

"name": "get",

"timestamp": 1569060494067090,

"duration": 3197,

"localEndpoint": {

"serviceName": "sleuth-cart",

"ipv4": "192.168.0.107"

},

"tags": {

"http.method": "GET",

"http.path": "/order/create"

}

},

{

"traceId": "94b954d843012ca9",

"parentId": "94b954d843012ca9",

"id": "bab70b1e69a5f3e3",

"kind": "SERVER",

"name": "get /cart/add/{cartid}",

"timestamp": 1569060494066140,

"duration": 8150,

"localEndpoint": {

"serviceName": "sleuth-cart",

"ipv4": "192.168.0.107"

},

"remoteEndpoint": {

"ipv4": "127.0.0.1",

"port": 49862

},

"tags": {

"http.method": "GET",

"http.path": "/cart/add/1",

"mvc.controller.class": "CartController",

"mvc.controller.method": "addToCart"

},

"shared": true

}

]

使用 RabbitMQ 情况

启动 zipkin,注意参数

java -jar zipkin-server-2.16.2-exec.jar --RABBIT_ADDRESSES=localhost:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest --RABBIT_VIRTUAL_HOST=/

启动 rabbitmq

rabbitmq-server

在测试的时候发现 mq 和以上方式时延相差无几,但是随着线程数的增加也就是并发量的增加,mq 传输时延将会大大低于 http。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。


http://chatgpt.dhexx.cn/article/kSa9fKHu.shtml

相关文章

集成sleuth_整合Sleuth

Sleuth是 springcloud 分布式跟踪解决方案。 Sleuth 术语: 跨度(span ) :Sleuth 的基本工作单元,他用一个64位的id唯一标识。出ID外,span还包含 其他的数据,如 描述,时间戳事件,键值对注解等&am…

Spring Boot 中的 Sleuth 是什么, 如何使用

Spring Boot 是一个非常流行的 Java Web 开发框架,它提供了许多方便的功能,其中之一就是 Sleuth。Sleuth 是一个分布式跟踪系统,用于跟踪应用程序中的请求和操作。在本文中,我们将探讨 Spring Boot 中的 Sleuth 是什么&#xff0c…

sleuth原理分析

背景 微服务模式下,一次请求可能会经过多个服务。如果没有日志链将单次请求的日志串起来,定位问题时很容易陷入海量的日志中,无法快速定位问题。 sleuth是spring cloud中日志链(调用链解决方案),引入该依赖…

快速学习-Sleuth--链路追踪

Sleuth–链路追踪 6.1 链路追踪介绍 在大型系统的微服务化构建中,一个系统被拆分成了许多模块。这些模块负责不同的功能,组合成 系统,最终可以提供丰富的功能。在这种架构中,一次请求往往需要涉及到多个服务。互联网应用构建 在…

SpringCloud学习笔记(十二)Sleuth 分布式请求链路跟踪

目录 一、Sleuth介绍 1、为什么会出现这个技术?需要解决哪些问题? 2、是什么 二、搭建链路监控步骤 1、zipkin搭建安装 1)下载 2)运行jar 3)运行控制台 4)术语 2、服务提供者 cloud-provider-pa…

MySQL5种索引类型

一、简介 MySQL目前主要有以下几种索引类型: 1.普通索引 2.唯一索引 3.主键索引 4.组合索引 5.全文索引 二、语句 CREATE TABLE table_name[col_name data type] [unique|fulltext][index|key][index_name](col_name[length])[asc|desc] 1.unique|fulltext为可选…

mysql索引类型和索引方式

1.什么是索引 在MySQL中,索引(index)也叫做“键(key)”,它是存储引擎用于快速找到记录的一种数据结构。 2.索引的分类 在MySQL中,通常我们所指的索引类型,有以下几种:…

Mysql索引的类型(单列索引、组合索引 btree索引 聚簇索引等)

一、索引的类型 Mysql目前主要有以下几种索引类型:FULLTEXT,HASH,BTREE,RTREE。 FULLTEXT 即为全文索引,目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用&…

mysql索引类型有哪些?

在Mysql数据库当中,我们经常会谈到Sql语句,当然也会谈到索引优化,那么在数据库当中有哪些索引类型呢,博主在这里进行分享,希望对大家能有所帮助。 目录 1、B-Tree索引: 2、Hash索引: 3、Full…

什么是索引?Mysql目前主要的几种索引类型

一、索引 MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。 打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。 索引分单列索引和组合索引。…

Mysql索引类型与索引方法

写在前面: 乍一看这两个概念可能有点混,先上一张发图。 索引类型就是我们平常说的唯一索引,主键索引,组合索引等索引类型。 我们都知道索引是一种数据结构,到底我们建的索引应该以什么样的结构存储呢?存储…

MYSQL 索引类型

一、索引类型 在数据库表中,对字段建立索引可以大大提高查询速度。假如我们创建了一个 mytable表 代码如下: CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL ); 我们随机向里面插入了10000条记录,其中有一条:555…

常见索引类型

日常开发工作中,涉及到的数据存储,要做查询优化或想深入了解存储引擎,需要对索引知识有个起码的了解,下面介绍下最常见的四种索引结构。 位图索引哈希索引BTREE索引倒排索引 1、位图索引(BitMap) 位图索引…

数据库的五种索引类型

本文从如何建立mysql索引以及介绍mysql的索引类型,再讲mysql索引的利与弊,以及建立索引时需要注意的地方 首先:先假设有一张表,表的数据有10W条数据,其中有一条数据是nicknamecss,如果要拿这条数据的话需要些的sql是 SELECT * FROM award WHERE nickname css 一般情况下,在没…

mysql索引有哪些类型?

MySQL目前主要有的索引类型为:普通索引、唯一索引、主键索引、组合索引、全文索引。 通过给字段添加索引可以提高数据的读取速度,提高项目的并发能力和抗压能力。索引优化时mysql中的一种优化方式。索引的作用相当于图书的目录,可以根据目录…

你知道多少种索引?

前言 嗨,大家好,我是fancy呀。 在工作中我们常常用到索引,无论是普通索引还是唯一索引,都是一些常用的索引方式,目的就是为了提高查询效率,避免业务请求超时等问题。那么,当你在使用索引的时候…

动态规划算法 | 最长递增子序列

通过查阅相关资料发现动态规划问题一般就是求解最值问题。这种方法在解决一些问题时应用比较多,比如求最长递增子序列等。 有部分人认为动态规划的核心就是:穷举。因为要求最值,肯定要把所有可行的答案穷举出来,然后在其中找最值…

求最长递增子序列个数——C++

声明:本文原题主要来自力扣,记录此博客主要是为自己学习总结,不做任何商业等活动! 一、下面是原题描述 给定一个未排序的整数数组,找到最长递增子序列的个数。 示例 1: 输入: [1,3,5,4,7] 输出: 2 解释: 有两个最长递…

最长递增子序列(LIS)

最长递增子序列(LIS) 问题描述: 求一个序列的最长递增子序列,这样的子序列是允许中间越过一些字符的,即留“空”。 例如:4 2 3 1 5 的最长递增子序列为 2 3 5,长度为 3 。 解法:…

【Leetcode】最长递增子序列问题及应用

文章目录 最长递增子序列问题及应用300. 最长递增子序列面试题 17.08. 马戏团人塔354. 俄罗斯套娃信封问题面试题 08.13. 堆箱子1691. 堆叠长方体的最大高度406. 根据身高重建队列 最长递增子序列问题及应用 300. 最长递增子序列 请参考 【Leetcode】计算最长系列&#xff08…