随着互联网架构的扩张,分布式系统变得日趋复杂,
越来越多的组件开始走向分布式化,如微服务、消息收发、分布式数据库、
分布式缓存、分布式对象存储、跨域调用,这些组件共同构成了繁杂的分布式网络,
那现在的问题是一个请求经过了这些服务后其中出现了一个调用失败的问题,
只知道有异常,但具体的异常在哪个服务引起的就需要进入每一个服务里面看日志,
这样的处理效率是非常低的。因此分布式调用链跟踪非常需要的。
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如下:
下图显示了Span和Trace以及Zipkin批注在系统中的联系:
Spring Cloud Sleuth自动生成Span、Trace等信息的。并默认采用http方式向Zipkin Server发送采集信息。
spring-boot2.0后官方不推荐自定义zipkin-server。可以之前去zipkin官网下载
最新的可执行jar包。
官网地址:https://zipkin.io/pages/quickstart,
本文下载jar为zipkin-server-2.19.2-exec.jar。
下载完成后再jar目录控制执行如下代码,即可启动服务。
java -jar zipkin-server-2.19.2-exec.jar
启动成功后,浏览器访问http://127.0.0.1:9411/zipkin/,可看到zipkin服务可视化界面
新建一个maven工程,命名为zipkin。zipkin工程的pom.xml为如下内容:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.smallstepgroupId>
<artifactId>zipkinartifactId>
<packaging>pompackaging>
<version>1.0-SNAPSHOTversion>
<modules>
<module>Service1module>
<module>Service2module>
modules>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.9.RELEASEversion>
<relativePath/>
parent>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<java.version>1.8java.version>
<spring-cloud.version>Greenwich.SR4spring-cloud.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
project>
接着创建调用服务service1子模块,其pom.xml配置引入相关依赖,完整pom.xml文件内容如下
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>zipkinartifactId>
<groupId>com.smallstepgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>Service1artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-zipkinartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
project>
再编写service1子模块的启动类
@SpringBootApplication
public class Service1Application {
public static void main(String[] args) {
SpringApplication.run(Service1Application.class, args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
其中注入一个RestTemplate实例,后续使用该实例调用其他服务。
接着进行配置application.yml文件,使得工程链路信息能收集到zipkin服务上。
完整配置内容如下:
server:
port: 8600
spring:
application:
name: service1
zipkin:
base-url: http://127.0.0.1:9411/
sender:
type: web
sleuth:
sampler:
probability: 1.0
然后编写调用接口类MessageController,代码如下:
@RestController
public class MessageController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/get")
public String getMessage(@RequestParam("name")String name){
return restTemplate.getForObject("http://127.0.0.1:8700/get?name="+name,String.class);
}
}
服务调用方工程编写完成,接着编写被调用工程。创建被调用服务service2子模块,
pom.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>zipkin</artifactId>
<groupId>com.smallstep</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Service2</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
启动类内容如下:
@SpringBootApplication
public class Service2Application {
public static void main(String[] args) {
SpringApplication.run(Service2Application.class, args);
}
}
被调用接口代码如下:
@RestController
public class MessageController {
@GetMapping("/get")
public String getMessage(@RequestParam("name")String name){
return "Hi " + name + ".";
}
}
application.yml配置如下:
server:
port: 8700
spring:
application:
name: service2
zipkin:
base-url: http://127.0.0.1:9411/
sender:
type: web
sleuth:
sampler:
probability: 1.0
配置完成后启动俩个服务。访问http://127.0.0.1:8600/get?name=IT_LiGe。
界面出现如下:
Hi IT_LiGe.
然后再去访问http://127.0.0.1:9411/zipkin/界面。点击查找出现如下界面:
然后点击第一条数据可以查看到具体的调用情况和时长,如下图:
也可以查看服务之间的依赖情况可以,点击“依赖”菜单,结果界面如下:
由于zipkin默认信息存储在内存内,然后zipkin服务重启就会导致历史数据丢失,但是我们
往往需要对历史数据查看。zipkin本身集成mysql和elasticsearch的数据持久化。
这边介绍下elasticsearch持久化实现方式。
elasticsearch下载地址:https://www.elastic.co/cn/downloads/elasticsearch
(以windows环境为例)下载好之后将其解压到你想要安装的目录:比如我的 D:\Program Files。
进入到D:\Program Files\elasticsearch-7.5.1\bin中,双击执行 elasticsearch.bat 。
等待打印信息输出完之后打开浏览器,输入:http://localhost:9200,
可以看到elasticsearch相关信息。
使用如下命令重新启动zipkin服务:
java -jar zipkin-server-2.19.2-exec.jar --STORAGE_TYPE=elasticsearch --ES_HOSTS=http://127.0.0.1:9200
再次访问http://127.0.0.1:8600/get?name=IT_LiGe,然后重启服务。再进行查看zipkin可视化界面,
,发现数据还是存在,说明数据已经持久化存储到ES上。
pinpoint和Apache SkyWalking技术。
pinpoint和skywalking都是基于字节码注入技术,可以做到完全的代码无侵入。对现有系统的改造极小。
源代码地址:https://gitee.com/LeeJunProject/spring_cloud_learning/tree/master/zipkin
欢迎扫描下图关注公众号 IT李哥,公众号经常推送一些优质的技术文章