Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Disable Ribbon and just use FeignClient in Spring Cloud

I am aware that we can force FeignClient to use OkHttp instead of Ribbon by providing the url Ex. @FeignClient(url="serviceId", name="serviceId")

I want the OkHttpClient to be used even when just the name is provided. Ex. @FeignClient(name="serviceId")

As per the spring cloud documentation "if Ribbon is enabled it is a LoadBalancerFeignClient, otherwise the default feign client is used."

How can I disable ribbon so that the default feign client will be used.

like image 606
Vidhyashankar Madheswaraswamy Avatar asked Apr 10 '18 12:04

Vidhyashankar Madheswaraswamy


People also ask

Does spring cloud gateway use ribbon?

Spring Cloud Loadbalancer is a generic abstraction that can do the work that we used to do with Netflix's Ribbon project. Spring Cloud still supports Netflix Ribbon, but Netflix Ribbons days are numbered, like so much else of the Netflix microservices stack, so we've provided an abstraction to support an alternative.

Can we use feign client without Eureka?

Yes you can use Feign without Ribbon, All you need to do is specify the base url in your Feign Java interface class.

Does feign client use ribbon?

Ribbon is a client side load balancer which gives you a lot of control over the behaviour of HTTP and TCP clients. Feign already uses Ribbon, so if you are using @FeignClient then this section also applies. A central concept in Ribbon is that of the named client.


1 Answers

None of the solutions on the internet worked for me.

  1. Simply setting an absolute url in the url portion resulted in loadbalancing exceptions
// this resulted in java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: localhost

@Lazy
@Configuration
@Import(FeignClientsConfiguration.class)
public class MyConfig {

    @LocalServerPort
    private int port;

    @Bean
    public MyClient myClient(final Decoder decoder, final Encoder encoder, final Client client) {
        return Feign.builder().client(client)
            .encoder(encoder)
            .decoder(decoder)
            .target(MyClient.class, "http://localhost:" + localServerPort);
    }
}
  1. setting spring.cloud.loadbalancing.ribbon.enabled=false resulted in application context problems. Additional settings needs to be disabled for this to work. I did not probe further
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'eurekaLoadBalancerClientConfiguration': Invocation of init method failed; nested exception is java.lang.NullPointerException

    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:160)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:416)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595)
...
...

My working solution

Finally, after inspecting the source code in org.springframework.cloud.openfeign.ribbon.DefaultFeignLoadBalancedConfiguration, I came up with this solution

@Lazy // required for @LocalServerPort to work in a @Configuration/@TestConfiguration
@TestConfiguration
@Import(FeignClientsConfiguration.class)
public class MyConfig {

    @LocalServerPort
    private int port;

    @Bean
    public MyClient myClient(Decoder decoder, Encoder encoder, Client client, Contract contract) {
        return Feign.builder().client(client)
            .encoder(encoder)
            .decoder(decoder)
            .contract(contract)
            .target(MyClient.class, "http://localhost:" + localServerPort);
    }

    // provide a default `FeignClient` so that Spring will not automatically create their LoadBalancingFeignClient
    @Bean
    public Client feignClient(SpringClientFactory clientFactory) {
        return new Client.Default(null, null);
    }
}
like image 183
Isen Ng Avatar answered Sep 30 '22 09:09

Isen Ng