分布式链路追踪,是一种用于分析和监控应用程序的方法,尤其是那些使用微服务架构的那些应用。分布式链路跟踪有助于查找故障发生位置和导致性能低下的原因。
SpringCloud全家桶中,整合了Sleuth和Zipkin做分布式链路跟踪和数据的收集展示。
Sleuth:为服务之间调用提供链路追踪。通过 Sleuth 可以很清楚的了解到一个服务请求经过了哪些服务,每个服务处理花费了多长。
Zipkin:可以使用它来收集各个服务器上请求链路的跟踪数据,并通过它提供的 REST API 接口来辅助我们查询跟踪数据以实现对分布式系统的监控程序,从而及时地发现系统中出现的延迟升高问题并找出系统性能瓶颈的根源。
Spring Cloud Zipkin 整合了Sleuth和Zipkin的功能,提供了一套完整的分布式链路解决方案。
代码可以在SpringBoot组件化构建https://www.pomit.cn/java/spring/springcloud.html中的Zipkin组件中查看,并下载。
首发地址:
品茗IT-首发
如果大家正在寻找一个java的学习环境,或者在开发中遇到困难,可以加入我们的java学习圈,点击即可加入,共同学习,节约学习时间,减少很多在学习中遇到的难题。
使用zipkin,要明白zipkin的客户端和服务端的概念:
首先要安装zipkin的服务端,就是一个jar包,启动之后收集客户端数据并做展示。
Zipkin开源地址:https://github.com/openzipkin/zipkin
当你首次接触zipkin时,一定会各种博客上的文章给绕晕的,乱七八糟,各种写法,这是因为Spring Cloud版本不同,提供的功能逐渐丰富,而且zipkin也提供了快读部署的方案。
我当前使用的Spring Cloud zipkin版本为2.1.0.RELEASE。zipkin在github的提交最新记录为Commits on Oct 25, 2019。
下面开始讲安装:
很多博客都是写的自己打包编译zipkin,然后用@EnableZipkinServer注解Spring boot应用来启动zipkin服务端。这种方式已经被官网遗弃,@EnableZipkinServer注解也被标记为@Deprecated。
所以,它给了一种更简单的部署方案:
curl -sSL https://zipkin.io/quickstart.sh | bash -s
java -jar zipkin.jar
如果用 Docker 的话,直接
docker run -d -p 9411:9411 openzipkin/zipkin
然后通过9411端口访问即可,比如我的是:http://10.247.62.23:9411
需要引入spring-boot-starter-web和spring-cloud-starter-zipkin;
因为使用了consul做服务注册发现,需要引入spring-cloud-starter-consul-discovery和spring-cloud-starter-netflix-ribbon。
依赖如下:
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>cn.pomitgroupId>
<artifactId>springcloudworkartifactId>
<version>0.0.1-SNAPSHOTversion>
parent>
<artifactId>SleuthZipkinartifactId>
<name>SleuthZipkinname>
<url>http://maven.apache.orgurl>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<java.version>1.8java.version>
<maven-jar-plugin.version>2.6maven-jar-plugin.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-zipkinartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-consul-discoveryartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-ribbonartifactId>
dependency>
dependencies>
project>
父模块pom文件可以在https://www.pomit.cn/spring/SpringCloudWork/pom.xml获取。
这里使用yaml文件写配置,配置文件application.yml:
application.yml:
server:
port: 8111
spring:
application:
name: sleuthZipkin
sleuth:
web:
client:
enabled: true
sampler:
probability: 1.0 # 将采样比例设置为 1.0,也就是全部都需要。默认是 0.1
zipkin:
base-url: http://10.247.62.23:9411/ # 指定了 Zipkin 服务器的地址
cloud:
consul:
host: 10.247.62.23
port: 8500
discovery:
prefer-ip-address: true
healthCheckPath: /consul/health
这里,应用名称是sleuthZipkin,在8111端口监听。
配置完成后,之后就是普通的调用和服务了。下面的第四章节将代码展示出来,第五章节介绍下链路跟踪zipkin的展示和用法。
我这里启动了三个服务做测试,分别为consulServer、consulClient和sleuthZipkin。
链路是从sleuthZipkin -> consulClient -> consulServer.
使用@EnableDiscoveryClient注解启动类, @EnableDiscoveryClient是将项目作为客户端注册到注册中心的注解,开启服务发现功能。
SleuthZipkinApplication :
package cn.pomit.springbootwork.zipkin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableDiscoveryClient
@SpringBootApplication
public class SleuthZipkinApplication {
public static void main(String[] args) {
SpringApplication.run(SleuthZipkinApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
这里的RestTemplate使用@LoadBalanced注解,我们跟踪RestTemplate的时候可以看到,RestTemplate多了个LoadBalancerInterceptor。
不管是服务注册还是服务调用,都需要写健康检查接口。前面写了我们健康检查地址是/consul/health,这里要开放个接口,让consul来检查身体。
package cn.pomit.springbootwork.zipkin.web;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/consul")
public class HealthWeb {
@RequestMapping(value = "health", method = { RequestMethod.GET })
public String health() {
return "check health";
}
}
如果我们使用Ribbon做服务调用,需要使用RestTemplate,这个RestTemplate是标识为负载均衡的。我们来调用上一篇提供的ip服务:
IpInfoService :
package cn.pomit.springbootwork.zipkin.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import cn.pomit.springbootwork.zipkin.model.ResultModel;
@Service
public class IpInfoService {
/**
* 第一个consulServer是配置文件种的spring.application.name,第二个是controller中配置的路径
*/
public static String remoteIpServiceUrl = "http://consulClient/consulClient/ip";
@Autowired
private RestTemplate restTemplate;
public ResultModel getIpInfo() {
ResponseEntity<ResultModel> ipModel = restTemplate.getForEntity(remoteIpServiceUrl, ResultModel.class);
return ipModel.getBody();
}
}
这里,第一个consulClient是服务提供方配置文件种的spring.application.name,第二个consulClient是服务提供方的controller中配置的路径。我们使用统一的实体ResultModel进行数据接收转换。
SleuthZipkinRest :
package cn.pomit.springbootwork.zipkin.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import cn.pomit.springbootwork.zipkin.model.ResultModel;
import cn.pomit.springbootwork.zipkin.service.IpInfoService;
@RestController
@RequestMapping("/sleuthTest")
public class SleuthZipkinRest {
@Autowired
IpInfoService ipInfoService;
@RequestMapping(value = "/ip", method = { RequestMethod.GET })
public ResultModel ip() {
return ipInfoService.getIpInfo();
}
}
我这里对三个服务调用链路sleuthZipkin -> consulClient -> consulServer的不同形式做测试和分析,下面是分析的几种情况:
只有sleuthZipkin开启了sleuth和zipkin。consulClient 和consulServer都未开启zipkin。
这种情况下,只显示sleuthZipkin调用consulClient的情况,展示两个应用的调用情况:
如果将consulServer停掉,会显示sleuthZipkin调用consulClient的异常情况,只能到consulClient,展示两个应用的调用情况:
sleuthZipkin和consulClient 都开启了sleuth和zipkin。consulServer为最后调用级别,不开启zipkin了。
这种情况下,显示sleuthZipkin -> consulClient -> consulServer的调用情况:
如果将consulServer停掉,会显示consulClient调用consulServer的异常情况,会显示完整的调用链:
过程中用到了ResultModel实体,作为统一的实体来用。
ResultModel:
详细完整的实体,可以访问品茗IT-博客《SpringCloud技术指南系列(十四)分布式锁之Zookeeper实现》进行查看
品茗IT-博客专题:https://www.pomit.cn/lecture.html汇总了Spring专题、Springboot专题、SpringCloud专题、web基础配置专题。
Spring项目快速开发工具:
一键快速构建Spring项目工具
一键快速构建SpringBoot项目工具
一键快速构建SpringCloud项目工具
一站式Springboot项目生成
Mysql一键生成Mybatis注解Mapper
Spring组件化构建
SpringBoot组件化构建
SpringCloud服务化构建
喜欢这篇文章么,喜欢就加入我们一起讨论SpringCloud使用吧!