Spring Boot进阶(93):体验式教程:手把手教你整合Spring Boot和Zipkin

📣前言

分布式系统开发中,服务治理是一个比较重要的问题。为了更好地实现服务治理,需要解决服务跟踪问题,即如何对分布式系统中的服务进行监控和追踪。本文将介绍如何使用Zipkin进行服务跟踪,并结合Spring Boot进行整合和应用。

那么,具体如何实现呢?这将又会是干货满满的一期,全程无尿点不废话只抓重点教,具有非常好的学习效果,拿好小板凳准备就坐!希望学习的过程中大家认真听好好学,学习的途中有任何不清楚或疑问的地方皆可评论区留言或私信,bug菌将第一时间给予解惑,那么废话不多说,直接开整!Fighting!!

🌊环境说明

开发工具:IDEA 2021.3

JDK版本: JDK 1.8

Spring Boot版本:2.3.1 RELEASE

Maven版本:3.8.2


🏆本文收录于《Spring Boot从入门到精通》,专门攻坚指数提升,2023 年国内最系统+最强(更新中)。

本专栏致力打造最硬核 Spring Boot 从零基础到进阶系列学习内容,🚀均为全网独家首发,打造精品专栏,专栏持续更新中...欢迎大家订阅持续学习。 如果想快速定位学习,可以看这篇【SpringBoot教程导航帖】,你想学习的都被收集在内,快速投入学习!!两不误。


🌊摘要

本文将简要介绍Zipkin的基本概念及其在服务跟踪中的应用,并详细讲解如何使用Spring Boot进行Zipkin的集成和应用,以及将Zipkin与ELK等技术进行整合。同时,本文还将分析Zipkin的优缺点,并提供测试用例和总结结论。

🌊正文


概述

Zipkin是一个开源的分布式跟踪系统。它可以帮助开发人员更好地实现服务跟踪,并对于服务之间的调用关系和性能进行监控和追踪。Zipkin支持多种语言和框架,并且具有开箱即用的设计,使得它成为开发人员首选的服务跟踪工具。

搭建Spring Boot应用

首先,我们先创建个基础的Spring Boot项目,如果还不会点这里,此处就不详细赘述啦。

Spring Boot集成教学

Spring Boot与Zipkin的集成非常的简单,只需要进行以下几个步骤即可:

  1. 添加相关依赖
java 复制代码
   <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-zipkin</artifactId>
   </dependency>
  1. 在application.yml或者application.properties中添加相关配置
java 复制代码
   spring.zipkin.base-url=http://localhost:9411

在这里,我们将Zipkin Server的地址设置为本地地址:http://localhost:9411,这是Zipkin Server的默认地址,也是我们在本地测试中常用的地址。

  1. 添加注解@EnableZipkinServer或者@EnableZipkinStreamServer
java 复制代码
   @SpringBootApplication
   @EnableZipkinServer
   public class ZipkinServerApplication {
   
   	public static void main(String[] args) {
   		SpringApplication.run(ZipkinServerApplication.class, args);
   	}
   
   }

这里我们使用的是@EnableZipkinServer注解,表示我们正在启用Zipkin Server。如果你想采用Zipkin Stream方式,则可以使用@EnableZipkinStreamServer注解替代。

在完成以上步骤后,我们就可以启动Zipkin Server并将其集成到Spring Boot应用中了。

应用场景案例

下面我们以微服务环境下用户服务调用订单服务为例,介绍Zipkin在服务跟踪中的应用。

当用户请求用户服务的时候,如果需要调用订单服务,则用户服务将向Zipkin提交一个Span,表示这是一个新的跟踪点。当用户服务完成对订单服务的调用后,会再次向Zipkin提交一个Span,表示这个跟踪点已经结束。这样,我们就可以在Zipkin中很方便地进行服务跟踪,并查看服务之间的调用关系。

通过Zipkin,我们可以清晰地查看服务之间的调用关系,并方便地定位服务问题。

实战教学

接下来我们就来介绍如何在Spring Boot应用中实现Zipkin的服务跟踪。我们将采用上述的用户服务和订单服务的例子进行说明。

创建Spring Boot应用

首先,我们需要创建一个Spring Boot应用,以用户服务为例。

java 复制代码
@SpringBootApplication
@RestController
public class UserServiceApplication {

    @Autowired
    private RestTemplate restTemplate;

    private static final Logger LOG = LoggerFactory.getLogger(UserServiceApplication.class);

    @RequestMapping("/getUserInfo")
    public String getUserInfo() {
        LOG.info("Get user info...");
        String orderServiceUrl = "http://localhost:8082/getOrderInfo";
        String response = restTemplate.getForObject(orderServiceUrl, String.class);
        return "user service response: " + response;
    }

    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

在上述代码中,我们创建了一个名为UserServiceApplication的Spring Boot应用,用于返回用户信息。在getUserInfo方法中,我们使用RestTemplate对象调用订单服务,获取订单信息。需要注意的是,此处我们只是简单的调用了订单服务,没有涉及任何服务跟踪的操作。

集成Zipkin

在完成用户服务的创建后,我们需要集成Zipkin,以便进行服务跟踪。按照Spring Boot集成教学中的步骤,我们可以很方便地集成Zipkin。

在application.yml中添加以下配置:

yml 复制代码
spring.application.name=user-service
spring.zipkin.base-url=http://localhost:9411

这里我们指定了应用名称和Zipkin Server的地址,以便Zipkin能够正确地将服务跟踪到当前的应用中。

接下来,我们需要创建一个RestTemplate实例,并使用Zipkin将其进行包装。

java 复制代码
@Bean
public RestTemplate restTemplate() {
    return new RestTemplate(new OkHttp3ClientHttpRequestFactory())
        .builder()
        .additionalInterceptor(new TraceIdRequestInterceptor())
        .additionalInterceptor(new TraceRequestInterceptor())
        .build();
}

在这里,我们创建了一个RestTemplate实例,并使用TraceIdRequestInterceptor和TraceRequestInterceptor对其进行包装。这两个拦截器的作用是在进行服务调用的时候,向Zipkin Server进行跟踪并生成Span。

java 复制代码
public class TraceIdRequestInterceptor implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        request.getHeaders().add("X-B3-TraceId", String.valueOf(Tracing.currentTracer().getCurrentSpan().context().traceId()));
        return execution.execute(request, body);
    }
}

public class TraceRequestInterceptor implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        Span span = Tracing.currentTracer().nextSpan();
        span.name(request.getURI().toString());
        try (Tracer.SpanInScope ws = Tracing.currentTracer().withSpanInScope(span)) {
            span.start();
            request.getHeaders().add("X-B3-SpanId", String.valueOf(span.context().spanId()));
            ClientHttpResponse response = execution.execute(request, body);
            span.finish();
            return response;
        } catch (RuntimeException | IOException | Error e) {
            span.error(e);
            throw e;
        }
    }
}

在上述代码中,TraceIdRequestInterceptor用于生成TraceId,并将其添加到请求头中;TraceRequestInterceptor用于生成Span,并在Span范围内执行请求。

最后,我们需要添加@EnableZipkinTracing注解,以启用Zipkin跟踪。

java 复制代码
@SpringBootApplication
@RestController
@EnableZipkinTracing
public class UserServiceApplication {

    ...

}

这样,我们就可以在Spring Boot应用中进行Zipkin服务跟踪了。

测试服务跟踪

在完成用户服务的创建和Zipkin集成后,我们需要进行测试,看看Zipkin是否能够正确地跟踪服务。

在完成服务启动后,我们可以通过浏览器的方式进行测试。

访问:http://localhost:8081/getUserInfo

具体操作

在上述教学中,我们已经介绍了如何在Spring Boot应用中集成Zipkin,并进行服务跟踪。但是,在实际的应用中,我们还需要更加完善的操作,以便更好地使用Zipkin进行服务治理。

1. 使用Feign进行服务调用

上述教学中,我们使用的是RestTemplate进行服务调用。但是,在Spring Cloud中,我们推荐使用Feign进行服务调用,因为Feign具有更加简单、直观和方便的服务调用方式。

使用Feign进行服务调用非常简单,只需要添加以下依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

然后,在应用启动类上添加@EnableFeignClients注解即可。接下来,我们需要创建一个Feign客户端,用于调用订单服务:

java 复制代码
@FeignClient(name = "order-service")
public interface OrderServiceClient {

    @GetMapping("/getOrderInfo")
    String getOrderInfo();

}

在上述代码中,我们创建了一个名为OrderServiceClient的Feign客户端,并使用@GetMapping注解指定了调用的地址。接下来,在用户服务中调用该服务:

java 复制代码
@Autowired
private OrderServiceClient orderServiceClient;

@RequestMapping("/getUserInfo")
public String getUserInfo() {
    LOG.info("Get user info...");
    String response = orderServiceClient.getOrderInfo();
    return "user service response: " + response;
}

这样,我们就使用了Feign进行服务调用。因为Feign已经集成了Zipkin,所以我们无需进行任何额外的配置即可实现服务跟踪。

2. Zipkin数据持久化

在使用Zipkin进行服务跟踪的同时,我们还需要进行数据的持久化操作。Zipkin支持多种数据存储方式,包括In-Memory、MySql、Elasticsearch等。在本教学中,我们将使用Elasticsearch进行数据持久化。

首先,我们需要添加以下依赖:

xml 复制代码
<dependency>
  <groupId>io.zipkin.java</groupId>
  <artifactId>zipkin-autoconfigure-storage-elasticsearch-http</artifactId>
  <version>${zipkin.version}</version>
</dependency>

然后,在application.yml中添加以下配置:

yml 复制代码
spring.zipkin.storage.type: elasticsearch
spring.zipkin.storage.elasticsearch.base-url: http://localhost:9200

这里我们指定了Zipkin存储数据的方式为Elasticsearch,并指定了Elasticsearch的地址。

最后,我们还需要添加数据存储的索引:

sh 复制代码
curl -XPUT 'http://localhost:9200/zipkin' -d '{
 "settings":{
  "index":{
   "number_of_shards":1,
   "number_of_replicas":0
  }
 }
}'

这样,我们就完成了Zipkin数据持久化的操作。

拓展操作

1. 将Zipkin与ELK整合

除了使用Elasticsearch对Zipkin进行数据持久化外,我们还可以将Zipkin与ELK进行整合,以便实现更好的服务跟踪和日志分析功能。

首先,我们需要添加以下依赖:

xml 复制代码
<dependency>
  <groupId>io.zipkin.java</groupId>
  <artifactId>zipkin-autoconfigure-ui</artifactId>
  <scope>runtime</scope>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-zipkin-elasticsearch</artifactId>
</dependency>

然后,在application.yml中添加以下配置:

yml 复制代码
spring.cloud.stream.kafka.binder.zkNodes: localhost:2181
spring.cloud.stream.bindings.zipkinStream.group: zipkin
spring.zipkin.sender.type: rabbit
spring.zipkin.sender.rabbitmq.addresses: localhost:5672
spring.zipkin.sender.rabbitmq.username: guest
spring.zipkin.sender.rabbitmq.password: guest
spring.zipkin.collector.rabbitmq.queue: zipkin
spring.zipkin.collector.rabbitmq.connection-timeout: 5000
spring.zipkin.collector.rabbitmq.concurrency: 1
spring.zipkin.collector.rabbitmq.exchange: zipkin-exchange
spring.zipkin.collector.rabbitmq.routing-key: zipkin

zipkin.storage.type: elasticsearch
zipkin.storage.elasticsearch.hosts: http://localhost:9200
zipkin.ui.static.queries: classpath:/zipkin-elasticsearch-queries.json

在这里,我们指定了Zipkin数据的发送方式为RabbitMQ,并将Zipkin数据发送至Elasticsearch中进行存储。同时,我们还指定了Zipkin UI的静态查询文件。

接下来,我们需要在ELK中创建相应的索引。以Logstash为例,我们可以使用以下的配置:

conf 复制代码
input {
  rabbitmq {
    host => "localhost"
    queue => "zipkin"
    durable => true
    exclusive => false
    auto_delete => false
    user => "guest"
    password => "guest"
    codec => "json"
    exchange => "zipkin-exchange"
    key => "zipkin"
    heartbeat => 10
    add_field => {"[@metadata][routing_key]" => "%{routing_key}"}
  }
}
filter {
  json {
    source => "message"
    add_field => {"[@metadata][collector_timestamp]" => "%{timestamp}"}
  }
  date {
    match => ["[@metadata][collector_timestamp]", "UNIX_MS"]
    target => "@timestamp"
  }
}

output {
  if [@metadata][routing_key] == "zipkin" {
    elasticsearch {
      hosts => ["http://localhost:9200"]
      manage_template => false
      index => "zipkin-%{+YYYY.MM.dd}"
      document_type => "span"
    }
  }
}

在完成以上配置后,我们就可以通过ELK实现更好的服务跟踪和日志分析功能。

2. 使用Zipkin进行性能监控

除了服务跟踪和日志分析外,Zipkin还可以用于性能监控。我们可以通过Zipkin记录服务调用时间和性能瓶颈,从而找出服务的性能问题并进行优化。

具体操作非常简单,只需要在Zipkin中查看服务调用耗时和性能瓶颈即可。在Zipkin的UI中,我们可以点击Span,并查看其下方的Timing和Dependencies选项卡,以便获得更多的性能信息。

总结

本文主要介绍了如何使用Spring Boot进行Zipkin集成和应用,以及将Zipkin与ELK等技术进行整合。通过本文的学习,我们可以掌握Zipkin的基本概念和操作,从而更好地实现服务跟踪、性能监控和日志分析等功能。

... ...

ok,以上就是我这期的全部内容啦,如果还想学习更多,你可以看看如下的往期热文推荐哦,每天积累一个奇淫小知识,日积月累下去,你一定能成为令人敬仰的大佬。

「赠人玫瑰,手留余香」,咱们下期拜拜~~

🌊 热文推荐

滴~如下推荐【Spring Boot 进阶篇】的学习大纲,请小伙伴们注意查收。

Spring Boot进阶(01):Spring Boot 集成 Redis,实现缓存自由

Spring Boot进阶(02):使用Validation进行参数校验

Spring Boot进阶(03):如何使用MyBatis-Plus实现字段的自动填充

Spring Boot进阶(04):如何使用MyBatis-Plus快速实现自定义sql分页

Spring Boot进阶(05):Spring Boot 整合RabbitMq,实现消息队列服务

Spring Boot进阶(06):Windows10系统搭建 RabbitMq Server 服务端

Spring Boot进阶(07):集成EasyPoi,实现Excel/Word的导入导出

Spring Boot进阶(08):集成EasyPoi,实现Excel/Word携带图片导出

Spring Boot进阶(09):集成EasyPoi,实现Excel文件多sheet导入导出

Spring Boot进阶(10):集成EasyPoi,实现Excel模板导出成PDF文件

Spring Boot进阶(11):Spring Boot 如何实现纯文本转成.csv格式文件?

Spring Boot进阶(12):Spring Boot 如何获取Excel sheet页的数量?

Spring Boot进阶(13):Spring Boot 如何获取@ApiModelProperty(value = "序列号", name = "uuid")中的value值name值?

Spring Boot进阶(14):Spring Boot 如何手动连接库并获取指定表结构?一文教会你

Spring Boot进阶(15):根据数据库连接信息指定分页查询表结构信息

Spring Boot进阶(16):Spring Boot 如何通过Redis实现手机号验证码功能?

Spring Boot进阶(17):Spring Boot如何在swagger2中配置header请求头等参数信息

Spring Boot进阶(18):SpringBoot如何使用@Scheduled创建定时任务?

Spring Boot进阶(19):Spring Boot 整合ElasticSearch

Spring Boot进阶(20):配置Jetty容器

Spring Boot进阶(21):配置Undertow容器

Spring Boot进阶(22):Tomcat与Undertow容器性能对比分析

Spring Boot进阶(23):实现文件上传

Spring Boot进阶(24):如何快速实现多文件上传?

Spring Boot进阶(25):文件上传的单元测试怎么写?

Spring Boot进阶(26):Mybatis 中 resultType、resultMap详解及实战教学

Spring Boot进阶(27):Spring Boot 整合 kafka(环境搭建+演示)

Spring Boot进阶(28):Jar包Linux后台启动部署及滚动日志查看,日志输出至实体文件保存

Spring Boot进阶(29):如何正确使用@PathVariable,@RequestParam、@RequestBody等注解?不会我教你,结合Postman演示

Spring Boot进阶(30):@RestController和@Controller 注解使用区别,实战演示

... ...

若想系统完整的从0到1的学习,可以参考这篇专栏总结《2023最新首发,全网最全 Spring Boot 学习宝典(附思维导图)》本专栏致力打造最硬核 Spring Boot 进阶系列学习内容,🚀均为全网独家首发,打造精品专栏,专栏持续更新中。欢迎大家订阅持续学习。

如果想快速定位学习,可以看这篇【教程导航帖】导航目录,你想学习的都被收集在内,快速投入学习!!两不误。

在入门及进阶之途,我必助你一臂之力,系统性学习,从入门到精通,带你不走弯路,直奔终点;投资自己,永远性价比最高,都这么说了,你还不赶紧来学??

本文涉及所有源代码,均已上传至GitHub开源,供同学们一对一参考 GitHub传送门,同时,原创开源不易,欢迎给个star🌟,想体验下被🌟的感jio,非常感谢❗

📣文末

我是bug菌,CSDN | 阿里云 | 华为云 | 51CTO 等社区博客专家,历届博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,掘金 | InfoQ | 51CTO等社区优质创作者,全网粉丝合计15w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板等海量资料。

相关推荐
我不是混子几秒前
什么是Java 的 Lambda 表达式?
java·后端
小蝙蝠侠11 分钟前
JMeter 执行流程
java·jmeter
程序员小假1 小时前
我们来说一说 ThreadLocal 内存泄漏
java·后端
xq95271 小时前
获取Facebook 散列利器 来了 十六进制到 Base64 转换器
java
我不是混子1 小时前
聊聊Spring事件机制
java·后端
DKPT1 小时前
JVM栈溢出时如何dump栈信息?
java·jvm·笔记·学习·spring
DKPT1 小时前
JVM堆大小如何设置?
java·开发语言·jvm·笔记·学习
铅笔侠_小龙虾1 小时前
JVM 目录
java·jvm
yunxi_051 小时前
让大模型会“说话”:基于 Spring WebSocket 的毫秒级流式 RAG 对话
java·后端
用户6120414922131 小时前
jsp+servlet做的医院挂号看诊管理系统
java·javascript·mysql