OpenFeign的@FeignClient注解不指定URL报错:Load balancer does not have available server for client

思路:Bug探明->源码解读->解决

问题描述与背景

先贴一下完整报错栈:

java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: x.x.x.x

    at org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient.execute(LoadBalancerFeignClient.java:91)
    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:119)
    at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:89)
    at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100)
    at com.sun.proxy.$Proxy199.createTaskGroup(Unknown Source)
    at com.finchina.automatic.upgrade.feign.FeignTest.test(FeignTest.java:27)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

背景介绍:接到一个需求调用外部Http接口,之前有接触过Feign故想着在这个新项目实战一下,没想到遇到之前没遭遇过的BUG。

        

如上图,项目POM引入的是OpenFeign,之前用的是Feign。两者的差异其一就是OpenFeign集成了负载均衡的实现,这也是为什么笔者遭遇接下来的BUG。

下面贴图一开始快速搭建,单元测试看Feign是否能调通下游接口的Service。

一开始为了快速调通,所以url直接写死的线下环境,发起Http请求,可以正常收到Response。后面为了实现Url可通过Nacos配置,删除了注解中的Url,在Config类中指定Host的Target。

运行直接报错 java.lang.RuntimeException!

深入排查与原理探明

@FeignClient注解未指定Url时,Url为"", 这里会直接Return;

分为以下几种情况:

1、Url不为空,且Url不包含 #{}时,且Url包含 :// ,则输出为原本Url

2、Url不为空,且Url不包含 #{}时,但Url包含 :// ,则输出为http:// + 原本Url(注意这里如果构成的不是URL,则会抛出异常)

3、Url为空或Url包含 #{}时,直接返回

显然当前的情况为3,接下来继续看为什么返回为空导致Feign负载均衡从而触发去注册中心查找注册的当前服务(服务端并未注册在注册中心,故找不到对应服务,因而报错)。

原来是FeignClientFactoryBean构造这里,当url为空时: 会构造Url为http:// + name, 然后返回了采用loadBalance负债均衡的Client!

顺利成章的,后面在执行的时候,因为Client已经是LoadBalanceFeignClient了,故这里执行的execute接口方法的实现也就是LoadBalanceFeignClient的实现了,如下图:

解决方案

解决方法也很简单,省流方法:随便在@FeignClient注解指定Url,只要不是空值就可以。

笔者这里就写个EMPTY占位,暂时不想考虑太复杂的改法,等有时间可以深挖一下,应该是可以在构建Client时候手动指定为Default in Client的。

发起调用,看一下是否解决问题:

调上游接口正常返回Response,问题解决!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值