整合Spring Cloud Sleuth编码实践
基于Spring Cloud Sleuth的链路追踪实现思路
笔者将创建三个微服务实例工程,这里直接使用第 8 章的源码 spring-cloud-alibaba-openfeign-demo
项目,该项目的调用链路是 order-service
通过 OpenFeign
组件分别调用 shopcart-service
和 goods-service
,如图 12-3 所示。
为了组件整合和演示需要,笔者将调用链路改为 order-service
通过 OpenFeign
组件调用 shopcart-service
,shopcart-service
通过 OpenFeign
组件调用 goods-service
,如图 12-4 所示。


代码基础改造
-
修改项目内容。
修改项目名称为
spring-cloud-alibaba-sleuth-zipkin-demo
,之后把各个模块中pom.xml
文件的artifactId
修改为spring-cloud-alibaba-sleuth-zipkin-demo
。修改项目的启动端口,分别为
8201
、8204
和8207
,主要是为了做章节区分。 -
增加测试接口。
打开
goods-service-demo
项目,在NewBeeCloudGoodsAPI
类中新增测试接口,代码如下:@GetMapping("/goodsDetail2/{goodsId}") public String goodsDetail2(@PathVariable("goodsId") int goodsId) { // 根据id查询商品并返回给调用端 if (goodsId < 1 || goodsId > 100000) { return "查询商品为空,当前服务的端口号为:" + applicationServerPort; } String goodsName = "商品" + goodsId; // 返回信息给调用端 return goodsName + ", 当前服务的端口号为" + applicationServerPort; }
-
新增
OpenFeign
代码。打开
shopcart-service-demo
项目中的pom.xml
文件,在dependencies
标签下引入OpenFeign
的依赖文件,新增代码如下:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency>
在
shopcart-service-demo
项目中新建ltd.shopcart.cloud.newbee.openfeign
包,在openfeign
包中新增NewBeeGoodsDemoService
文件,用于创建对商品服务的Feign
调用。NewBeeGoodsDemoService.java
代码如下:package ltd.shopcart.cloud.newbee.openfeign; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(value = "newbee-cloud-goods-service", path = "/goodsDetail2") public interface NewBeeGoodsDemoService { @GetMapping(value = "/{goodsId}") String getGoodsDetail2(@PathVariable(value = "goodsId") int goodsId); }
-
增加配置,启用
OpenFeign
并使FeignClient
生效。在
shopcart-service-demo
项目的启动类上添加@EnableFeignClients
注解,并配置相关的FeignClient
类,代码如下:@SpringBootApplication @EnableFeignClients(clients={ltd.shopcart.cloud.newbee.openfeign.NewBeeGoodsDemoService.class}) public class ShopCartServiceApplication { public static void main(String[] args) { SpringApplication.run(ShopCartServiceApplication.class, args); } }
-
使用
OpenFeign
声明的接口实现服务通信。由于已经使用
OpenFeign
声明了相关接口且配置完毕,因此这里修改NewBeeCloudShopCartAPI
类中的代码并增加对goods-service
项目中接口的远程调用就可以了。修改
NewBeeCloudShopCartAPI
类的代码如下:@RestController public class NewBeeCloudShopCartAPI { @Value("${server.port}") private String applicationServerPort; // 读取当前应用的启动端口 @Resource private NewBeeGoodsDemoService newBeeGoodsDemoService; @GetMapping("/shop-cart/{cartId}") public String cartItemDetail(@PathVariable("cartId") int cartId) { String detail2Result = newBeeGoodsDemoService.getGoodsDetail2(2025); // 根据id查询商品并返回给调用端 if (cartId < 0 || cartId > 100000) { return "查询购物项为空,当前服务的端口号为:" + applicationServerPort; } String cartItem = "购物项" + cartId; // 返回信息给调用端 return cartItem + ",当前服务的端口号为:" + applicationServerPort; } }
之后,尝试启动三个项目,并在浏览器中请求 order-service
的测试接口,如果一切正常就表示代码修改成功。如此一来,就将调用链路改成了 order-service→shopcart-service→goods-service。
整合 Spring Cloud Sleuth 编码
前面已经完成了对演示代码的基础修改,接下来主要讲解 Spring Cloud Sleuth
的整合过程。
-
开启 OpenFeign 的日志输出。
为了后续功能演示的效果,需要打开
OpenFeign
组件的日志输出功能,这样就能够把OpenFeign
远程调用接口的日志内容打印出来。在
order-service-demo
项目和shopcart-service-demo
项目中分别新建ltd.order.cloud.newbee.config
包和ltd.shopcart.cloud.newbee.config
包,用于存放OpenFeign
日志输出的配置类。之后在刚刚创建的两个config
包下新建OpenFeignConfiguration
类,用于设置OpenFeign
的日志级别,代码如下:@Configuration public class OpenFeignConfiguration { @Bean public Logger.Level openFeignLogLevel() { // 设置 OpenFeign 的日志级别 return Logger.Level.FULL; } }
修改
order-service-demo
项目和shopcart-service-demo
项目中的application.properties
配置文件,分别新增如下配置项:# order-service-demo 项目 # 演示需要,开启 OpenFeign debug 级别日志 logging.level.ltd.order.cloud.newbee.openfeign=debug # shopcart-service-demo 项目 # 演示需要,开启 OpenFeign debug 级别日志 logging.level.ltd.shopcart.cloud.newbee.openfeign=debug
完成后,一旦项目中有用到
OpenFeign
远程调用的情况,就会在控制台输出对应的日志信息。当然,开启
OpenFeign
日志输出后,读者也可以启动三个项目并调用测试接口,可以记录一下此时的日志信息,方便后续与整合Sleuth
组件后的日志进行比对。笔者在功能测试时就记录了一下,获取的日志信息如下:2023-06-01 23:54:42.104 DEBUG 6860 --- [nio-8114-exec-2]
-
引入
Sleuth
依赖。依次打开
order-service-demo
、goods-service-demo
、shopcart-service-demo
项目中的pom.xml
文件,在dependencies
标签下引入Sleuth
的依赖文件,新增代码如下:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency>
整合
Spring Cloud Sleuth
组件是很简单的,不需要做额外的配置,只要添加依赖文件即可。重启三个项目并调用测试接口,此时获取的日志信息就变了,内容如下:当然,不止
OpenFeign
调用时的日志会被打标,平时打印的一些日志信息也会被打标。为了给读者演示,笔者在NewBeeCloudOrderAPI
类中新增如下测试代码:private static final Logger log = LoggerFactory.getLogger(NewBeeCloudOrderAPI.class); @GetMapping("/logTest") public String logTest() { // 平时会打印的日志 log.info("test info log by sleuth"); log.error("test error log by sleuth"); try { int i = 1 / 0; } catch (Exception e) { // 将异常信息通过日志输出 log.error("test exception log by sleuth:", e); } return "logTest"; }
整合
Sleuth
后,打印的日志信息中也出现了打标信息,代码如下:
这样一来,在项目开发与维护时,一旦出现异常或错误信息都可以通过打标数据查找上下游的数据,对更快地定位错误有非常大的帮助。
打标的日志信息数据已经产生,但仅靠开发人员手工组织和串联这些不计其数的链路日志显然不现实,因此还需要部署链路追踪数据的分析工具 Zipkin
来完成这个工作。