如何使用 Feign.Builder 实现 Sleuth Tracing?
How to implement Sleuth Tracing With Feign.Builder?
我正在尝试将 Sleuth 集成到我们的系统中。如果我使用带有 @FeignClient
注释的接口,一切正常。这些接口会自动检测,并且 Sleuth headers 通过 REST 调用传播。
但是,我们有一些现有代码直接使用带有 Feign 注释接口的 Feign.Builder(只是没有使用 @FeignClient
注释)。这段代码添加了一些自定义的请求拦截器、编码器、代理等。
例如:
// Feign REST interface
public interface MyService {
@RequestMapping(method = RequestMethod.GET, value = "/version")
String getVersion();
}
// Creating the builder
Feign.Builder builder = Feign.builder();
builder.requestInterceptor(new MyCustomInterceptor());
// + adding proxy, encoder, decoder, etc
// Using the builder
MyService myService = builder.target(MyService.class, "http://localhost:8080/myservice");
myService.getVersion();
我希望这个旧代码能够传播 Sleuth headers。有什么简单的方法可以连接起来吗?
(我想一个选择是重新设计我们的 Feign 接口以使用 @FeignClient 并重新设计所有自定义拦截器、编码器等的应用方式,但最终这可能会带来很多风险。 )
我是否需要做一个特殊的请求拦截器来手动注入这些(例如从自动装配的 Tracer)?有没有一种干净的方法(或现有的 class)来做到这一点?
我终于明白了。
答案差不多就在这里:https://github.com/spring-cloud/spring-cloud-sleuth/issues/594
当使用Feign.Builder时,它的Client需要被"Trace"实现包装。
为此,我们只需声明一个客户端 bean,然后 spring/sleuth 将自动处理包装它(因为 sleuth 在依赖列表中)。
声明类似于:
@Bean
public OkHttpClient okHttpClient() {
return new OkHttpClient();
}
然后我们可以在构建客户端实现时将该客户端 bean 传递给构建器。
例如:
// autowiring the Client bean
@Autowired
private Client client;
// using the Client bean to build the Feign client
DemoClient demoClient = Feign.builder()
.client(client)
.target(DemoClient.class, "http://localhost:8200/demo");
之后,似乎一切正常。我可以看到 Trace Id 传播到远程 REST 服务。
我一直在和 Feign、FeignBuilder 和 zipkin 纠缠。
对我来说,使用 FeignClient 并在属性文件中配置 Feign,它起作用了。
@FeignClient(value = "ms-common--zipkin-test2")
public interface Client2 {
@GET
@Path("/request1")
String request1(@QueryParam("payload") String payload);
}
在application.yml
feign:
client:
config:
ms-common--zipkin-test2:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
requestInterceptors:
- com.organization.mscommonzipkintest1.framework.client.FeignUserAgentInterceptor
然后我在该包中创建了一个 FeignUserAgentInterceptor。
我正在尝试将 Sleuth 集成到我们的系统中。如果我使用带有 @FeignClient
注释的接口,一切正常。这些接口会自动检测,并且 Sleuth headers 通过 REST 调用传播。
但是,我们有一些现有代码直接使用带有 Feign 注释接口的 Feign.Builder(只是没有使用 @FeignClient
注释)。这段代码添加了一些自定义的请求拦截器、编码器、代理等。
例如:
// Feign REST interface
public interface MyService {
@RequestMapping(method = RequestMethod.GET, value = "/version")
String getVersion();
}
// Creating the builder
Feign.Builder builder = Feign.builder();
builder.requestInterceptor(new MyCustomInterceptor());
// + adding proxy, encoder, decoder, etc
// Using the builder
MyService myService = builder.target(MyService.class, "http://localhost:8080/myservice");
myService.getVersion();
我希望这个旧代码能够传播 Sleuth headers。有什么简单的方法可以连接起来吗?
(我想一个选择是重新设计我们的 Feign 接口以使用 @FeignClient 并重新设计所有自定义拦截器、编码器等的应用方式,但最终这可能会带来很多风险。 )
我是否需要做一个特殊的请求拦截器来手动注入这些(例如从自动装配的 Tracer)?有没有一种干净的方法(或现有的 class)来做到这一点?
我终于明白了。
答案差不多就在这里:https://github.com/spring-cloud/spring-cloud-sleuth/issues/594
当使用Feign.Builder时,它的Client需要被"Trace"实现包装。
为此,我们只需声明一个客户端 bean,然后 spring/sleuth 将自动处理包装它(因为 sleuth 在依赖列表中)。
声明类似于:
@Bean
public OkHttpClient okHttpClient() {
return new OkHttpClient();
}
然后我们可以在构建客户端实现时将该客户端 bean 传递给构建器。
例如:
// autowiring the Client bean
@Autowired
private Client client;
// using the Client bean to build the Feign client
DemoClient demoClient = Feign.builder()
.client(client)
.target(DemoClient.class, "http://localhost:8200/demo");
之后,似乎一切正常。我可以看到 Trace Id 传播到远程 REST 服务。
我一直在和 Feign、FeignBuilder 和 zipkin 纠缠。 对我来说,使用 FeignClient 并在属性文件中配置 Feign,它起作用了。
@FeignClient(value = "ms-common--zipkin-test2")
public interface Client2 {
@GET
@Path("/request1")
String request1(@QueryParam("payload") String payload);
}
在application.yml
feign:
client:
config:
ms-common--zipkin-test2:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
requestInterceptors:
- com.organization.mscommonzipkintest1.framework.client.FeignUserAgentInterceptor
然后我在该包中创建了一个 FeignUserAgentInterceptor。