问题
I'm trying to integrate Sleuth into our system. If I use interfaces annotated with @FeignClient
, everything works fine. These interfaces get instrumented automatically, and Sleuth headers get propagated with REST calls.
But, we have some existing code that uses Feign.Builder directly with Feign annotated interfaces (just not annotated with @FeignClient
). This code adds some custom request interceptors, encoder, proxy, etc.
For example:
// 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();
I would like this older code to propagate Sleuth headers. Is there some easy way to wire this up?
(I suppose one option is to rework our Feign interfaces to have @FeignClient and rework how all of the custom interceptors, encoders, etc get applied, but ultimately that might be a lot of work with a lot of risk.)
Do I need to do a special request interceptor to inject these manually (e.g. from an autowired Tracer)? Is there a clean way (or existing class) to do that?
回答1:
I finally figured it out.
The answer was pretty much here: https://github.com/spring-cloud/spring-cloud-sleuth/issues/594
When using Feign.Builder, its Client needs to be wrapped by a "Trace" implementation.
To accomplish this, we can just declare a Client bean, then spring/sleuth will automatically take care of wrapping it (since sleuth is in the dependency list).
The declaration will be something like:
@Bean
public OkHttpClient okHttpClient() {
return new OkHttpClient();
}
Then we can just pass that Client bean to the builder when building the client implementation.
For example:
// 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");
After doing that, everything seemed to work. I could see the Trace Id getting propagated to the remote REST service.
回答2:
I have been struggling with Feign, FeignBuilder and zipkin. For me, using FeignClient and configuring Feign in the properties file, it worked.
@FeignClient(value = "ms-common--zipkin-test2")
public interface Client2 {
@GET
@Path("/request1")
String request1(@QueryParam("payload") String payload);
}
in application.yml
feign:
client:
config:
ms-common--zipkin-test2:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
requestInterceptors:
- com.organization.mscommonzipkintest1.framework.client.FeignUserAgentInterceptor
And I created a FeignUserAgentInterceptor in that package.
来源:https://stackoverflow.com/questions/48211360/how-to-implement-sleuth-tracing-with-feign-builder