spring-cloud / spring-cloud-netflix

Integration with Netflix OSS components
http://cloud.spring.io/spring-cloud-netflix/
Apache License 2.0
4.87k stars 2.44k forks source link

How to change Zuul HttpClient for Eureka clients #1896

Closed dlvenable closed 7 years ago

dlvenable commented 7 years ago

We use Zuul in a number of services. Most use Eureka-discovered services on the backend, but others use direct URI requests. I'm also setting up AWS X-Ray for our services, which is a new request tracing service from AWS. They provide their own Apache HttpClientBuilder which automatically adds traces to requests that pass through it. I've gotten this working with RestTemplate requests, but now I'm trying to find out how to change it for Spring Cloud Zuul.

How can I change Spring Cloud Zuul's underlying Apache HttpClientBuilder or HttpClient?

ryanjbaxter commented 7 years ago

Out of the box we use the Apache HTTP client but you can choose the OK HTTP client of the (deprecated) Netflix RestClient. http://cloud.spring.io/spring-cloud-static/Dalston.RELEASE/#_zuul_http_client

If you want to use another HTTP client it should be possible but will be more work. Check out RibbonClientConfiguration which creates the necessary beans for the Ribbon client used by Zuul. When not using Ribbon the class SimpleHostRoutingFilter handles proxying the request. You can probably also provide your own bean of this type (maybe need to use @Primary) with the HTTP client you want to use.

dlvenable commented 7 years ago

To clarify, AWS provides a subclass of Apache HttpClient that we'd like to use. So ideally we'd just swap out the underlying HttpClient. Technically they provide a ClosableHttpClient. They also provide a subclass of Apache's HttpClientBuilder. So we still want to use Apache, but provide a different object.

ryanjbaxter commented 7 years ago

Makes sense, the approach above should work.

spencergibb commented 7 years ago

Seems like we could use an optional ObjectProvider<HttpClient> in RibbonLoadBalancingHttpClient.createDelegate().

dlvenable commented 7 years ago

It sounds like the only way to accomplish this with the current code is to create a new subclass of RibbonLoadBalancingHttpClient and override the createDelegate() method in order to modify one line.

Then we create our own bean for RibbonLoadBalancingHttpClient which essentially replaces all the code in HttpClientRibbonConfiguration. So we'd have to copy-and paste both most of createDelegate() and HttpClientRibbonConfiguration for this change.

Is that correct?

The ObjectProvider approach sounds very appealing. I take it that the consuming Spring Boot application would create a new bean of ObjectProvider<HttpClient> (or ObjectProvider<HttpClientBuilder>. Then the ribbonLoadBalancingHttpClient function would be able to detect that bean and pass it to the constructor. Does this seem about the right?

(All the above is just for Eureka/Ribbon services; not SimpleHostRoutingFilter)

ryanjbaxter commented 7 years ago

Sounds about right

lionelfarr commented 7 years ago

@dlvenable how did you solve this? We are looking to achieve the same thing. Could you share your solution?

ryanjbaxter commented 7 years ago

I am going to close this issue because it is now much easier to customize the underlying HttpClient with the work done in #2080.

dlvenable commented 7 years ago

@lionelfarr, I haven't seen #2080 yet, but what I ended up doing was creating my own Zuul pre and post filters. It was much easier that way. Though I did have to copy-and-paste (cringe) code from the AWS HttpClient.