前瞻:
首先我们知道spring Cloud Sleuth分布式服务跟踪是干什么的,在现如今的系统规模中,随着系统规模的越来越大,微服务之间的调用关系越来越错综复杂,通常一个前端的请求在系统中会经过多个微服务之间的调用最后才能返回正确的结果,而在这么多微服务之间的相互调用中,每一次微服务之间调用的延迟都可能使整个请求出现超时而导致失败,这时候,对于全链路调用的跟踪就显得尤为重要了,它记录了整个请求链路中每个微服务调用的信息,例如某一个微服务调用的处理时间等等,这对后续分析系统的性能瓶颈很有帮助;
实现:
第一步:
1、实现服务注册中心Eureka,这个很简单,不在赘述,读者可以看我前面代码的例子;
2、微服务应用trance-1:实现一个REST接口/trance-1,调用改接口后实现对微服务应用trance-2的接口调用
2.1:引入pom依赖:
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>spring.cloud</groupId>
<artifactId>trace-1</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.7.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>4.6</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2.2:配置文件:
spring:
application:
name: trace-1
server:
port: 9101
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/eureka/
2.3:启动类:
package controller;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication(scanBasePackages = "controller")
@EnableDiscoveryClient
public class TestApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
};
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
2.4:REST接口:
package controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@Slf4j
public class Trace1Controller {
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/trace-1" , method = RequestMethod.GET)
public String trace(){
log.info("=====call trace-1====");
return restTemplate.getForEntity("http://trace-2/trace-2", String.class)
.getBody();
}
}
3、微服务应用trance-2:pom配置、启动类基本相同,不同的是配置类和一个实现了REST接口/trance-2供trance-1调用
spring:
application:
name: trace-2
server:
port: 9102
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/eureka/
package controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController
@Slf4j
public class Trace2Controller {
@RequestMapping(value = "/trace-2" , method = RequestMethod.GET)
public String trace(HttpServletRequest request){
log.info("call trace-2");
log.info(request.getHeader("X-B3-TraceId")+" "
+ request.getHeader("X-B3-SpanId"));
//System.out.println("=====call trace-2=====");
return "trace2";
}
}
第二步:分别启动服务注册中心Eureka、trance-1和trance-2,请求/trance-1接口http://localhost:9101/trace-1
此时可以再trance-1和trance-2控制台看见如下信息:
trance-1控制台:
trance-2控制台:
下面我们来说下这几个参数的含义:
第一个值:trance-1,应用的名称,也就是配置文件application.yml中的spring.application.name的属性
第二个值:33c66de84a293041,spring Cloud Sleuth生成的一个ID,也叫tranceID,它用来表示一条请求链路,我们可以看到trance-1和trance-2应用中打印的tranceID都相同,这表示他们是一次请求,在一条请求链路上;
第三个值:7975c7c9fcf06b51,spring Cloud Sleuth生成的另一个ID,也叫spanID,它表示一个基本的工作单元,比如发送一个http请求。
第四个值:false,表示信息是否要输出到Zipkin等服务来进行后序的收集及展示;
上面四个值中,tranceID和spanID是spring Cloud Sleuth实现分布式服务跟踪的核心。