如何在 Spring Cloud 中禁用 Ribbon 并仅使用 FeignClient
Posted
技术标签:
【中文标题】如何在 Spring Cloud 中禁用 Ribbon 并仅使用 FeignClient【英文标题】:How to Disable Ribbon and just use FeignClient in Spring Cloud 【发布时间】:2018-09-20 02:43:04 【问题描述】:我知道我们可以通过提供 url Ex 来强制 FeignClient 使用 OkHttp 而不是 Ribbon。 @FeignClient(url="serviceId", name="serviceId")
即使只提供了名称,我也希望使用 OkHttpClient。前任。 @FeignClient(name="serviceId")
根据 Spring Cloud 文档“如果启用了 Ribbon,则它是 LoadBalancerFeignClient,否则使用默认的 feign 客户端。”
如何禁用功能区以便使用默认的 feign 客户端。
【问题讨论】:
ribbon 是一个负载均衡器,我们不使用它的 http 客户端,所以我有点困惑。你可以用丝带 OkHttp。这就是你想要的吗? Netflix FeignClient 默认会寻找负载均衡器。我想在没有负载均衡器的情况下使用 OkHttp。我可以通过在@feignClient
注释中提供 url 和 name 属性来实现这一点。但我想知道是否可以通过在@feignclient
注释中提供 name 属性来实现相同的目标。
只使用名称将始终使用负载均衡器
所以即使功能区不在类路径上,它仍然会寻找负载均衡器。正确的?是否可以通过某种解决方法覆盖该行为?
如果功能区不在类路径上,那么 url 来自哪里?
【参考方案1】:
互联网上的解决方案都不适合我。
-
只需在
url
部分设置绝对 url 就会导致负载平衡异常
// 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);
-
设置
spring.cloud.loadbalancing.ribbon.enabled=false
导致应用程序上下文问题。需要禁用其他设置才能使其正常工作。我没有进一步探究
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)
...
...
我的工作解决方案
最后,在查看org.springframework.cloud.openfeign.ribbon.DefaultFeignLoadBalancedConfiguration
中的源代码后,我想出了这个解决方案
@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);
【讨论】:
【参考方案2】:它与 Ribbon 无关。
检查一下:
feign:
httpclient:
enabled: false
这将禁用 spring cloud 自动配置的 httpclient,并将在上下文中搜索名为 httpClient
的 @Bean
。所以在@Configuration
类中提供@Bean
的定义,仅此而已。
在spring cloud feign中查看类FeignAutoConfiguration
。
https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html
【讨论】:
【参考方案3】:我有同样的问题,但我的设置有点不同,我没有让它在我的情况下工作(使用带有 spring mvc 样式注释的 spring-cloud-starter-openfeign)。
仅供参考:我需要一个带有 SSLSocketFactory 的自定义客户端,最后只为客户端创建了 bean 并将 URL 保留在 @FeignClient
@Bean
public Client myClient()
return new Client.Default(getSSLSocketFactory(), new NoopHostnameVerifier());
但是,我们确实有使用 spring-cloud-starter-feign 的项目,其中没有在注释上提供 URL。不确定下面的配置是否完整(我没有设置),但它可能会为您指明正确的方向...
依赖项
compile("org.springframework.cloud:spring-cloud-starter-feign")
exclude group: 'org.springframework.cloud', module: 'spring-cloud-starter-ribbon'
exclude group: 'org.springframework.cloud', module: 'spring-cloud-starter-archaius'
配置
@Configuration
@Import(FeignClientsConfiguration.class) // org.springframework.cloud.netflix.feign.FeignClientsConfiguration
public class MyConfig
@Value("$client.url")
private String url;
@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, url);
【讨论】:
以上是关于如何在 Spring Cloud 中禁用 Ribbon 并仅使用 FeignClient的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spring Cloud 中禁用 Ribbon 并仅使用 FeignClient