Spring Cloud Sleuth整合zipkin过程解析

这篇文章主要介绍了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在系统中的联系

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

导入依赖

  <!-- 引入 springboot 和 springcloud 父工程 -->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.6.RELEASE</version>
    <relativePath/>
  </parent>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Greenwich.SR3</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-zipkin</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.amqp</groupId>
      <artifactId>spring-rabbit</artifactId>
    </dependency>
    <!-- Springboot 相关 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

配置 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<String> 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<String> cartRes = restTemplate.getForEntity(cartUrl, String.class);
    ResponseEntity<String> 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

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

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

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

以下为一次全链路追踪的详细信息,包含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。

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

(0)

相关推荐

  • spring-cloud Sleuth的使用方法

    一直没弄明白sleuth的tracerContext是如何创建和传递的,闲来无事研究了一下.由于对sleuth的源码不熟悉,准备通过debug brave.Tracer的nextId()方法,查看方法调用栈来找来龙去脉. 首先创建两个service A和B,记作srvA.srvB,在srvA中添加testA controller,sevB中添加testB controller,testA中通过Feign调用testB. 先看当用户通过浏览器调用srvA的时候,srvA是作为server的. co

  • SpringCloud整合分布式服务跟踪zipkin的实现

    1.zipkin zipkin是Twitter的一个开源项目,它基于Google Dapper实现.我们可以使用它来收集各个服务器上请求链路的跟踪数据,并通过它提供的REST API接口来辅助我们查询跟踪数据以实现对分布式系统的监控程序,从而及时地发现系统中出现的延迟升高问题并找出系统性能瓶颈的根源.除了面向开发的API接口之外,它也提供了方便的UI组件来帮助我们直观的搜索跟踪信息和分析请求链路明细,比如:可以查询某段时间内各用户请求的处理时间等. zipkin的架构图如下: 由上面的架构图可以

  • 浅析springcloud 整合 zipkin-server 内存日志监控

    Zipkin Zipkin是一款开源的分布式实时数据追踪系统(Distributed Tracking System),基于 Google Dapper的论文设计而来,由 Twitter 公司开发贡献.其主要功能是聚集来自各个异构系统的实时监控数据. Zipkin主要包括四个模块  - Collector           接收或收集各应用传输的数据  - Storage            存储接受或收集过来的数据,当前支持Memory,MySQL,Cassandra,ElasticSea

  • SpringBoot集成Zipkin实现分布式全链路监控

    Zipkin 简介 Zipkin is a distributed tracing system. It helps gather timing data needed to troubleshoot latency problems in service architectures. Features include both the collection and lookup of this data. If you have a trace ID in a log file, you ca

  • 浅谈Spring-cloud 之 sleuth 服务链路跟踪

    这篇文章主要讲述服务追踪组件zipkin,Spring Cloud Sleuth集成了zipkin组件. 一.简介 Add sleuth to the classpath of a Spring Boot application (see below for Maven and Gradle examples), and you will see the correlation data being collected in logs, as long as you are logging re

  • 详解spring cloud分布式整合zipkin的链路跟踪

    为什么使用zipkin? 上篇主要写了:spring cloud分布式日志链路跟踪 从上篇中可以看出服务之间的调用,假设现在有十几台服务,那么在查找日志的时候比较繁琐.复杂,而且在查看调用的时候也会像蜘蛛网一样,量太大. 这时候zipkin可以把链路调用整个过程给升级起来,只需要到一个地方去查找,就可以知道哪一步出错. zipkin也分为服务器和客户端,服务器就是zipkin,微服务就是客户端. 首先,建立服务器zipkin 在此服务build.gradle加上zipkin的依赖: compil

  • SpringBoot+SpringCloud用户信息微服务传递实现解析

    这篇文章主要介绍了SpringBoot+SpringCloud实现登录用户信息在微服务之间的传递,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 实现思路: 1:准备一个ThreadLocal变量,供线程之间共享. 2:每个微服务对所有过来的Feign调用进行过滤,然后从请求头中获取User用户信息,并存在ThreadLocal变量中. 3:每个微服务在使用FeignClient调用别的微服务时,先从ThreadLocal里面取出user信息,并

  • SpringBoot2.0 ZipKin示例代码

    Zipkin是一种分布式跟踪系统.它有助于收集解决微服务架构中延迟问题所需的时序数据.它管理这些数据的收集和查找.Zipkin的设计基于 Google Dapper论文. 应用程序用于向Zipkin报告时间数据.Zipkin用户界面还提供了一个依赖关系图,显示每个应用程序有多少跟踪请求.如果您正在解决延迟问题或错误问题,则可以根据应用程序,跟踪长度,注释或时间戳过滤或排序所有跟踪.选择跟踪后,您可以看到每个跨度所需的总跟踪时间百分比,从而可以识别问题应用程序. 这是翻译过来的原意,自己在这里想如

  • Spring Cloud Sleuth整合zipkin过程解析

    这篇文章主要介绍了Spring Cloud Sleuth整合zipkin过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 SpringCloud Sleuth 简介 Spring Cloud Sleuth为Spring Cloud实现了分布式跟踪解决方案. Spring Cloud Sleuth借鉴了Dapper的术语. Span:基本的工作单元.Span包括一个64位的唯一ID,一个64位trace码,描述信息,时间戳事件,key-va

  • sentinel 整合spring cloud限流的过程解析

    spring cloud基于http进行服务调用,大致过程如下: 服务提供端:提供http接口,并向服务中心注册服务信息 服务消费端:将服务端的http接口作为本地服务,从注册中心读取服务提供端信息,使用feign发起远程调用 相关依赖 <!-- 服务注册与发现 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibab

  • spring boot 2整合swagger-ui过程解析

    这篇文章主要介绍了spring boot 2整合swagger-ui过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.添加mvn依赖 修改pom.xml加入 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.5.0</v

  • Spring Cloud Zuul添加过滤器过程解析

    这篇文章主要介绍了Spring Cloud Zuul添加过滤器过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Zuul作为网关的其中一个重要功能,就是实现请求的鉴权.而这个动作我们往往是通过Zuul提供的过滤器来实现的. 一.过滤器方法的作用 想要使用Zuul实现过滤功能,我们需要自定义一个类继承ZuulFilter类,并实现其中的四个方法,我们先看一下这四个方法的作用是什么 public class MyFilter extends

  • Spring Cloud Sleuth 和 Zipkin 进行分布式跟踪使用小结

    目录 什么是分布式跟踪? 分布式跟踪的关键概念 带有SpringCloudSleuth的SpringBoot示例 使用Zipkin可视化跟踪 分布式跟踪允许您跟踪分布式系统中的请求.本文通过了解如何使用 Spring Cloud Sleuth 和 Zipkin 来做到这一点. 对于一个做所有事情的大型应用程序(我们通常将其称为单体应用程序),跟踪应用程序内的传入请求很容易.我们可以跟踪日志,然后弄清楚请求是如何处理的.除了应用程序日志本身之外,我们无需查看其他任何内容. 随着时间的推移,单体应用

  • Spring Cloud Feign组成配置过程解析

    Feign的组成 接口 作用 默认值 Feign.Builder Feign的入口 Feign.Builder Client Feign底层用什么去请求 和Ribbon配合时:LoadBalancerFeignClient 不和Ribbon配合时:Fgien.Client.Default Contract 契约,注解支持 SpringMVCContract Encoder 解码器,用于将独享转换成HTTP请求消息体 SpringEncoder Decoder 编码器,将相应消息体转成对象 Res

  • Spring Boot 整合 Druid过程解析

    这篇文章主要介绍了Spring Boot 整合 Druid过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 概述 Druid 是阿里巴巴开源平台上的一个项目,整个项目由数据库连接池.插件框架和 SQL 解析器组成.该项目主要是为了扩展 JDBC 的一些限制,可以让程序员实现一些特殊的需求,比如向密钥服务请求凭证.统计 SQL 信息.SQL 性能收集.SQL 注入检查.SQL 翻译等,程序员可以通过定制来实现自己需要的功能. Druid 是

  • Spring boot整合log4j2过程解析

    这篇文章主要介绍了Spring boot整合log4j2过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 以前整合过log4j2,但是今天再次整合发现都忘记了,而且也没有记下来 1.pom.xml中 (1)把spring-boot-starter-web包下面的spring-boot-starter-logging排除 <dependency> <groupId>org.springframework.boot</gr

  • spring boot整合kafka过程解析

    这篇文章主要介绍了spring boot整合kafka过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.启动kafka 启动kafka之前一定要启动zookeeper,因为要使用kafka必须要使用zookeeper. windows环境下启动,直接使用kafka自带的zookeeper: E:\kafka_2.12-2.4.0\bin\windows zookeeper-server-start.bat ..\..\config\z

随机推荐