Spring Cloud Sleuth + Zipkin

一、分布式跟踪系统

在微服务架构中,众多的微服务之间互相调用,如何清晰地记录服务的调用链路是一个需要解决的问题。同时,由于各种原因,跨进程的服务调用失败时,运维人员希望能够通过查看日志和查看服务之间的调用关系来定位问题。
一个分布式服务跟踪系统主要由五部分构成:[ 数据采集、数据传输、数据存储 、数据分析、 数据可视化 ]

分布式服务跟踪系统设计理念:平台无关性、多语言支持、多中间件支持

二、Sleuth

Spring Cloud Sleuth 是为了对微服务之间调用链路进行跟踪的一个组件,Sleuth主要是数据采集

  1. Span:基本工作单元,例如,在一个新建的span中发送一个RPC等同于发送一个回应请求给RPC,span通过一个64位ID唯一表示,trace以另一个64位ID表示。span还有其他数据信息,比如摘要、时间戳事件、关键值注释(tags)、span的ID、以及进度ID(通常是IP地址) ,span在不断的启动和停止,同时记录了时间信息,当你创建了一个span,你必须在未来的某个时刻停止它;
  2. Trace:一系列spans组成的一个树状结构,例如,如果你正在跑一个分布式工程,你可能需要创建一个trace;
  3. Annotation:用来及时记录一个事件的存在,一些核心annotations用来定义一个请求的开始和结束。
    • cs - Client Sent -客户端发起一个请求,这个annotion描述了这个span的开始;
    • sr - Server Received -服务端获得请求并准备开始处理它,如果将其sr减去cs时间戳便可得到网络延迟;
    • ss - Server Sent -注解表明请求处理的完成(当请求返回客户端),如果ss减去sr时间戳便可得到服务端需要的处理请求时间;
    • cr - Client Received -表明span的结束,客户端成功接收到服务端的回复,如果cr减去cs时间戳便可得到客户端从服务端获取回复的所有所需时间。

在这里插入图片描述

链路日志由由 [appname,traceId,spanId,exportable] 组成的。

  • appname:服务的名称,也就是 spring.application.name 的值。
  • traceId:整个请求的唯一 ID,它标识整个请求的链路。
  • spanId:基本的工作单元,发起一次远程调用就是一个 span。
  • exportable:决定是否导入数据到 Zipkin 中。

2.1 抽样采集数据

如果服务的流量很大,全部采集对传输、存储压力比较大。这个时候可以设置采样率
Sleuth 可以通过配置spring.sleuth.sampler.probability=X.Y (如配置为1.0,则采样率为100%,采集服务的全部追踪数据),

#zipkin 抽样比例
spring.sleuth.sampler.probability=1.0

若不配置默认采样率是0.1(即10%)。
也可以通过实现bean的方式来设置采样为全部采样(AlwaysSampler)或者不采样(NeverSampler):如

@Bean
public Sampler defaultSampler() {
	return new AlwaysSampler();
} 

Sleuth采样算法的实现是 Reservoir sampling(水塘抽样)。实现类是 PercentageBasedSampler。

附水塘抽样算法:https://www.cnblogs.com/krcys/p/9121487.html

2.2 使用

服务调用方
  1. 引入jar包
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-sleuth-dependencies</artifactId>
            <version>3.0.0</version>
        </dependency>
</dependencyManagement>
  1. 修改yaml文件
server:
  port: 6001

spring:
  application:
    name: SleuthZipkinServer01
  sleuth:
    trace-id128: true  ## 允许打印日志
  sampler:
    probability: 1.0  ## 采样率
  1. 编写Controller
@RestController
public class DemoController {
    Logger log = LoggerFactory.getLogger(DemoController.class);
    @Autowired
    private RestTemplate restTemplate;
    @GetMapping("/test1")
    public String test1() {
        log.info("这里是SleuthZipkinServer01");
        return restTemplate.getForObject("http://127.0.0.1:6002/test1", String.class);
    }
}
  1. curl http://172.16.130.95:6001/test1

2021-05-22 13:38:44.664 INFO [SleuthZipkinServer01,60a898e4f1f46883ee833df45c8c21d4,ee833df45c8c21d4] 1240 --- [nio-6001-exec-8] com.zlf.controller.DemoController : 这里是SleuthZipkinServer01

服务被调用方
  1. 引入jar包
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-sleuth-dependencies</artifactId>
            <version>3.0.0</version>
        </dependency>
</dependencyManagement>
  1. 修改yaml文件
server:
  port: 6001

spring:
  application:
    name: SleuthZipkinServer02
  sleuth:
    trace-id128: true  ## 允许打印日志
  sampler:
    probability: 1.0  ## 采样率
  1. 编写Controller
@RestController
public class DemoController {
    Logger log = LoggerFactory.getLogger(DemoController.class);
    @GetMapping("/test1")
    public String test1() {
        log.info("这里是SleuthZipkinServer02~~test1");
        return "~~~~~~~server02~~test1~~~~~~~~~~~~~~~~~~";
    }
}
  1. curl http://172.16.130.95:6001/test1
    2021-05-22 13:38:44.668 INFO [SleuthZipkinServer02,60a898e4f1f46883ee833df45c8c21d4,382a1a74fda76399] 10044 --- [nio-6002-exec-5] com.zlf.controller.DemoController : 这里是SleuthZipkinServer02~~test1

三、Zipkin

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

Zipkin 提供了可插拔数据存储方式:In-Memory、MySql、Cassandra 以及 Elasticsearch。接下来的测试为方便直接采用 In-Memory 方式进行存储,生产推荐 Elasticsearch。
在这里插入图片描述

3.1 环境搭建

  1. 下载zipkin jar包
curl -fL -o 'zipkin.jar' 'https://maven.aliyun.com/repository/central/io/zipkin/zipkin-server/2.23.2/zipkin-server-2.23.2-exec.jar'
  1. 启动Zipkin
java -jar zipkin.jar

启动成功:
在这里插入图片描述
页面访问:
在这里插入图片描述
3. Zipkin Mysql方式存储配置

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.jar同级目录创建zipkin-server.properties文件:

zipkin.storage.type=mysql
zipkin.storage.mysql.host=localhost
zipkin.storage.mysql.port=3306
zipkin.storage.mysql.username=root
zipkin.storage.mysql.password=123

3.2 使用

服务调用方
  1. 引入jar包(在Sleuth基础上增加)
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>
  1. 修改yaml文件(在Sleuth基础上增加)
spring:
  zipkin:
    base-url: http://127.0.0.1:9411
  1. 编写Controller
@RestController
public class DemoController {
    Logger log = LoggerFactory.getLogger(DemoController.class);
    @Autowired
    private RestTemplate restTemplate;
    @GetMapping("/test2")
    public String test2() {
        log.info("这里是SleuthZipkinServer01");
        return restTemplate.getForObject("http://127.0.0.1:6002/test2", String.class);
    }
}
服务被调用方
  1. 引入jar包(在Sleuth基础上增加)
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>
<!-- 监控链路mysql数据库相关jar --> 
<dependency>
    <groupId>io.zipkin.brave</groupId>
    <artifactId>brave-instrumentation-mysql8</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
  1. 修改yaml文件(在Sleuth基础上增加)

主要是&queryInterceptors=brave.mysql8.TracingQueryInterceptor
&exceptionInterceptors=brave.mysql8.TracingExceptionInterceptor
&zipkinServiceName=myDatabaseService 配置

spring:
  zipkin:
    base-url: http://127.0.0.1:9411
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?useSSL=false&queryInterceptors=brave.mysql8.TracingQueryInterceptor&exceptionInterceptors=brave.mysql8.TracingExceptionInterceptor&zipkinServiceName=myDatabaseService&serverTimezone=UTC
    username: root
    password: 123
  1. 编写Controller
@RestController
public class DemoController {
    Logger log = LoggerFactory.getLogger(DemoController.class);
    @Autowired
    private UserService userService;
    @GetMapping("/test2")
    public String test2() {
        log.info("这里是SleuthZipkinServer02~~~test2");
        return userService.getUser();
    }
}
public interface UserService {
    public String getUser();
}
@Service
public class UserServiceImpl implements UserService {
    @Resource
    private JdbcTemplate jdbcTemplate;
    @Override
    public String getUser() {
        String sql = "select * from test_user";
        List<UserEntity> userList = (List<UserEntity>) jdbcTemplate.query(sql, new RowMapper<UserEntity>() {
            @Override
            public UserEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
                UserEntity user = new UserEntity();
                user.setId(rs.getInt("id"));
                user.setName(rs.getString("name"));
                return user;
            }
        });
        return userList.toString();
    }
}
  1. 观察Zipkin客户端

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、常见的链路追踪技术

  1. cat
    由大众点评开源,基于java开发的实时应用监控平台,包括实时应用监控,业务监控。继承方案是通过代码埋点的方式来实现监控,比如:拦截器,过滤器等。对代码的入侵性很大,集成成本较高,风险较大。
  2. zipkin
    由Twitter公司开源,开放源代码分布式的跟踪系统,用于手机服务的定时数据,以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。该产品结合spring-cloud-sleuth使用较为简单,集成很方便,但功能较简单。
  3. pinpoint
    由韩国人开源的基于字节码注入的调用链分析,以及应用监控分析工具,特点是支持多种插件,UI功能较强,接入端无代码入侵。
  4. skywalking
    是本土开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点和pinpoint差不多。
    下载:http://skywalking.apache.org/
    启动:java -javaagent:G:\github\incubator-skywalking\skywalking-agent\skywalking-agent.jar -Dskywalking.agent.service_name=test -jar app.jar
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Spring Cloud Sleuth是一个分布式跟踪解决方案,它可以帮助我们跟踪微服务架构中的请求流程和调用链路。它通过为每个请求生成唯一的跟踪ID和跟踪标记,来实现跨服务的请求追踪和监控。同时,它还提供了可视化的跟踪数据展示和分析工具,方便我们进行问题排查和性能优化。 ### 回答2: Spring Cloud Sleuth是一个分布式追踪系统,它提供了在分布式系统中跟踪和解决请求的能力。它可以帮助开发人员定位和解决系统中的性能问题。 Spring Cloud Sleuth通过在每个微服务之间添加唯一的跟踪标识符,跟踪请求的流程和路径。当一个请求进入系统时,Sleuth会为该请求生成一个唯一的跟踪ID,并将其传递给所有涉及的微服务。每个微服务都会将自己的操作和处理记录到这个跟踪ID下。 使用Spring Cloud Sleuth,开发人员可以方便地追踪和分析每个请求在系统中的耗时和路径。可以通过生成的跟踪ID查找请求的起始点和终点,以及每个微服务的处理时间。这对于识别瓶颈和优化系统性能非常有帮助。 此外,Sleuth还提供了与Zipkin等跟踪系统的集成,使得跨多个微服务的请求的追踪更加方便。通过将跟踪数据发送到Zipkin等跟踪系统,可以在集中的仪表板上查看和分析整个系统的追踪信息,从而更好地诊断和定位问题。 总之,Spring Cloud Sleuth提供了一个简单而有效的分布式追踪解决方案,帮助开发人员跟踪和解决系统中的性能问题。它可以方便地集成到Spring Cloud微服务架构中,使得微服务部署和调试更加方便和可靠。 ### 回答3: Spring Cloud Sleuth是一个分布式追踪解决方案,它可以帮助开发人员追踪分布式系统中的请求流程和跟踪调用链。它采用了Google的Dapper追踪系统设计思想,并将其与Spring Cloud框架结合起来,为开发人员提供了一套简单而强大的分布式追踪工具。 使用Spring Cloud Sleuth,可以轻松地生成唯一的追踪ID并将其传递给每个请求,以便在整个分布式系统中跟踪它们的传播和调用链。这些追踪ID可以在不同的微服务之间以属性的方式传递,从而实现了对请求的全局追踪。 Spring Cloud Sleuth通过在每个微服务之间注入拦截器和过滤器来实现追踪功能。当一个请求进入系统时,拦截器会生成一个唯一的追踪ID,并将其添加到请求头中,然后系统中的每个微服务都会自动将该追踪ID添加到自己的日志中,以便后续跟踪。通过检查这些日志,开发人员可以很容易地了解请求在系统中的传播和调用链。 除了追踪功能之外,Spring Cloud Sleuth还提供了一些其他有用的功能,例如在日志中添加关键的请求信息、生成报告和分析等。这些功能可以帮助开发人员快速定位和解决分布式系统中的问题。 总而言之,Spring Cloud Sleuth是一个强大的分布式追踪解决方案,它可以帮助开发人员追踪分布式系统中的请求流程和调用链。通过使用Sleuth,开发人员可以更轻松地理解和调试复杂的分布式系统,并提高系统的可观测性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

抽抽了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值