SpringCloud FeignClient的坑(httpClient连接池的使用)

在头条上已经发布过不少的文章了,根据文章的浏览量来看,go语言的市场需求明显是小于java的需求量的,最近也开始发布一下以前使用java和springcloud,springboot里遇到的一些避坑文章; 个人感觉go在云原生这个场景里将会不断地被发展,在云原生环境下,没有任何一个语言可能和其匹敌,RUST也许会有一定的竞争压力。 作为service mesh未来的云环境架构, springcloud的原有项目会慢慢地转换; 先说了些感悟, 今天要分享的是OpenFeign里的一个小坑。 OpenFeign是springcloud里用的比较多的http RPC的一个架构, FeignClient是这个架构中的一个Client的入口点。

 

在压力测试的过程中发现的问题;并发线程数较多时,持续一段时间后,开始出现请求失败。日志发现的错误有两种:

一种是ribbon报找不到目标服务,错误信息如下:

 

Caused by: com.netflix.client.ClientException: Load balancer does not have available server for client: halo-framework-example-server
at com.netflix.loadbalancer.LoadBalancerContext.getServerFromLoadBalancer(LoadBalancerContext.java:483)
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:184)
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:94)
at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:42)

 

 

一种是socket底层报出的Unkonw Host的错误

at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0_152]
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_152]
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_152]
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_152]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_152]
at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_152]
at sun.net.NetworkClient.doConnect(NetworkClient.java:175) ~[na:1.8.0_152]
at sun.net.www.http.HttpClient.openServer(HttpClient.java:463) ~[na:1.8.0_152]
at sun.net.www.http.HttpClient.openServer(HttpClient.java:558) ~[na:1.8.0_152]
at sun.net.www.http.HttpClient.<init>(HttpClient.java:242) ~[na:1.8.0_152]
at sun.net.www.http.HttpClient.New(HttpClient.java:339) ~[na:1.8.0_152]
at sun.net.www.http.HttpClient.New(HttpClient.java:357) ~[na:1.8.0_152]

 

 

查看feignclient的源代码

 


@Import({ HttpClientFeignLoadBalancedConfiguration.class,
		OkHttpFeignLoadBalancedConfiguration.class,
		DefaultFeignLoadBalancedConfiguration.class })
public class FeignRibbonClientAutoConfiguration {

 


@Configuration
@ConditionalOnClass(ApacheHttpClient.class)
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
class HttpClientFeignLoadBalancedConfiguration {

 

上面是autoconfiguration的方式对feignClient进行配置。 可以看到有三种方式, 分别是
HttpClientFeignLoadBalancedConfiguration.class, OkHttpFeignLoadBalancedConfiguration.class,

DefaultFeignLoadBalancedConfiguration.class

 

这三种方式, 其中最后一种方式
DefaultFeignLoadBalancedConfiguration是默认方式,也就是直接通过Httpclient进行http的调用,不使用连接池的方式,只有上面两种方式是支持连接池的方式, Openfeign组件通过类型ConditionONClass的方式,进行条件配置,如果引入了OKHttpClient或者Apache HttpClient的包才会使用到http的连接池, 由于默认是没有import这里的两个包,所以默认以不带连接池的实现方式来实现httpclient,也就出现上面的问题。

 

知道了问题所在,解决的方法,就是引入相应的宝贝即可。

 

 

posted @ 2022-08-31 15:47  菜菜聊架构  阅读(1111)  评论(0编辑  收藏  举报