这是我参与11月更文挑战的第30天,活动详情查看:2021最后一次更文挑战
本系列代码地址:github.com/JoJoTec/spr…
我们在这一节我们将继续讲解避免链路信息丢失做的设计,主要针对获取到现有 Span 之后,如何保证每个 GlobalFilter 都能保持链路信息。首先,我们自定义 Reactor 的核心 Publisher 即 Mono 和 Flux 的工厂,将链路信息封装进去,保证由这个工厂生成的 Mono 和 Flux,都是只要是这个工厂生成的 Mono 和 Flux 之间无论怎么拼接都会保持链路信息的:
自定义 Mono 和 Flux 的工厂
公共 Subscriber 封装,将 reactor Subscriber 的所有关键接口,都检查当前上下文是否有链路信息,即 Span,如果没有就包裹上,如果有则直接执行即可。
1 | csharp复制代码public class TracedCoreSubscriber<T> implements Subscriber<T>{ |
之后分别定义所有 Flux 的代理 TracedFlux,和所有 Mono 的代理 TracedMono,其实就是在 subscribe 的时候,用 TracedCoreSubscriber 包装传入的 CoreSubscriber:
1 | scala复制代码public class TracedFlux<T> extends Flux<T> { |
定义工厂类,使用请求 ServerWebExchange 和原始 Flux 创建 TracedFlux,以及使用请求 ServerWebExchange 和原始 Mono 创建 TracedMono,并且 Span 是通过 Attributes 获取的,根据前文的源码分析我们知道,这个 Attribute 是通过 TraceWebFilter 放入 Attributes 的。由于我们只在 GatewayFilter 中使用,一定在 TraceWebFilter 之后 所以这个 Attribute 一定存在。
1 | typescript复制代码@Component |
公共抽象 GlobalFilter - CommonTraceFilter
我们编写所有我们后面要实现的 GlobalFilter 的抽象类,这个抽象类的主要功能是:
- 保证继承这个抽象类的 GlobalFilter 本身以及拼接的链路中,是有链路信息的,其实就是保证它 filter 返回的 Mono 是由我们上面实现的 Factory 生成的即可。
- 不同 GlobalFilter 之间需要排序,有顺序的执行,这个通过实现 Ordered 接口即可
1 | kotlin复制代码package com.github.jojotech.spring.cloud.apigateway.filter; |
这样,我们就可以基于这个抽象类去实现需要定制的 GlobalFilter 了
微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer:
本文转载自: 掘金