链路追踪 trace 快速入门
基础应用
Spring Cloud Sleuth为服务之间调用提供链路追踪。通过Sleuth可以很清楚地了解到一个服务请求经过了哪些服务,每个服务处理花费了多长。从而可以很方便的理清各微服务间的调用关系。此外Sleuth还可以帮助我们进行耗时分析,通过Sleuth可以很方便的了解到每个采样请求的耗时,从而分析出哪些服务调用比较耗时;可视化错误,对于程序未捕捉的异常,可以通过集成Zipkin服务界面上看到;链路优化,对于调用比较频繁的服务,可以针对这些服务实施一些优化措施。
Spring Cloud Sleuth 特性
Spring Cloud Sleuth具有如下的特性:
- 提供对常见分布式跟踪数据模型的抽象:traces,spans(形成DAG),annotations和键值注解。 Spring Cloud Sleuth虽然基于HTrace,但与Zipkin(Dapper)兼容。
- Sleuth记录了耗时操作的信息以辅助延时分析。通过使用Sleuth,可以定位应用中的耗时原因。
- 为了不写入太多的日志,以至于使生产环境的应用程序崩溃,Sleuth做了如下的工作:
- 生成调用链的结构化数据
- 包括诸如自定义的织入层信息,比如HTTP
- 包括采样率配置以控制日志的容量
- 查询和可视化完全兼容Zipkin
- 为Spring应用织入通用的组件,如servlet filter、Zuul过滤器和Feign客户端等等
- Sleuth可以在进程之间传播上下文(也称为背包)。 因此,如果在Span上设置了背包元素,它将通过HTTP或消息传递下游,发送到其他进程
- Spring Cloud Sleuth 实现了OpenTracing的规范。OpenTracing通过提供平台无关、厂商无关的API,使得开发人员能够方便的添加(或更换)追踪系统的实现
项目准备
下面通过两个服务之间的相互调用,演示链路监控的场景。前期需要准备的项目有三个:
- Eureka Server:服务注册Server,作为其他客户端服务的注册中心;
- Sleuth Client A:客户端服务A,注册到Eureka Server。对外提供两个接口,一个接口暴露给客户端服务A,另一个接口调用客户端服务B,客户端服务之间通过Feign进行http调用;
- Sleuth Client B:同上。
Eureka Server
首先,依赖需要引入Netflix Eureka Server。
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
其次,配置Eureka Server的服务端信息。
spring:
application:
name: eureka-server-standalone
server:
port: 8761
eureka:
instance:
hostname: standalone
instance-id: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
如上配置文件所示,我们配置了单机模式的Eureka Server,服务器的端口号为8761。
最后,添加应用程序的入口类。
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
如上三步完成,我们的注册服务即可以正常启动。
Sleuth Client A
首先,也是引入客户端服务A所需要的依赖。
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
需要的基本依赖为:注册客户端、声明式客户端组件openfeign和Spring Boot Web包。
其次,客户端服务A的配置文件如下:
eureka:
instance:
instance-id: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
client:
service-url:
defaultZone: http://localhost:8761/eureka/, http://localhost:8762/eureka/
spring:
application:
name: service-a
server:
port: 9002
上述配置声明了服务名,feign通过服务名进行服务实例调用,指定了客户端服务A的端口号9002。A还需要注册到Eureka Server。
然后,就是提供两个接口,如下为其实现:
@RestController
@RequestMapping("/api")
public class ServiceAController {
@Autowired
ServiceBClient serviceBClient;
@GetMapping("/service-a")
public String fromServiceA(){
return "from serviceA";
}
@GetMapping("/service-b")
public String fromServiceB(){
return serviceBClient.fromB();
}
}
服务A提供了/service-b
接口,可以调用服务B,feign客户端的实现如下。/service-a
接口用以给服务B调用。
@FeignClient("service-b")
public interface ServiceBClient {
@RequestMapping(value = "/api/service-b")
public String fromB();
}
feign客户端的注解中,指定了要调用的服务B的serviceId为service-b
。
最后,应用程序的入口类如下:
@SpringBootApplication
@EnableFeignClients
public class ChapterClientServiceaApplication {
public static void main(String[] args) {
SpringApplication.run(ChapterClientServiceaApplication.class, args);
}
}
@EnableFeignClients
注解会扫描那些声明为feign客户端的接口。
如上,客户端服务A的实现大功告成。
Sleuth Client B
客户端服务B与A的实现基本类似,A与B之间实现互调。这里略过实现。
- 点赞
- 收藏
- 关注作者
评论(0)