Feign 使用HttpClient和OkHttp方式
使用httpclient和okhttp
在feign中,client是一个非常重要的组件,feign最终发送request请求以及接收response响应都是由client组件来完成的。client在feign源码中是一个接口,在默认情况下,client的实现类是client.default。client.default是由httpurlconnection来实现网络请求的。另外,client还支持httpclient和okhttp来进行网络请求。
首先查看feignribbonclient的自动配置类feignribbonclientautoconfiguration,该类在程序启动的时候注入一些bean,其中注入了一个beanname为feignclient的client类型的bean。在省缺配置beanname为feignclient的bean的情况下,会自动注入client.default这个对象,跟踪client.default源码,client.default使用的网络请求框架是httpurlconnection,代码如下:
public static class default implements client { private final sslsocketfactory sslcontextfactory; private final hostnameverifier hostnameverifier; public default(sslsocketfactory sslcontextfactory, hostnameverifier hostnameverifier) { this.sslcontextfactory = sslcontextfactory; this.hostnameverifier = hostnameverifier; } public response execute(request request, options options) throws ioexception { httpurlconnection connection = this.convertandsend(request, options); return this.convertresponse(connection, request); } ......//代码省略 }
这种情况下,由于缺乏连接池的支持,在达到一定流量的后服务肯定会出问题 。
使用httpclient
那么如何在feign中使用httpclient的框架呢?我们查看feignautoconfiguration.httpclientfeignconfiguration的源码:
@configuration @conditionalonclass({apachehttpclient.class}) @conditionalonmissingclass({"com.netflix.loadbalancer.iloadbalancer"}) @conditionalonmissingbean({closeablehttpclient.class}) @conditionalonproperty( value = {"feign.httpclient.enabled"}, matchifmissing = true ) protected static class httpclientfeignconfiguration { private final timer connectionmanagertimer = new timer("feignapachehttpclientconfiguration.connectionmanagertimer", true); @autowired( required = false ) private registrybuilder registrybuilder; private closeablehttpclient httpclient; protected httpclientfeignconfiguration() { } @bean @conditionalonmissingbean({httpclientconnectionmanager.class}) public httpclientconnectionmanager connectionmanager(apachehttpclientconnectionmanagerfactory connectionmanagerfactory, feignhttpclientproperties httpclientproperties) { final httpclientconnectionmanager connectionmanager = connectionmanagerfactory.newconnectionmanager(httpclientproperties.isdisablesslvalidation(), httpclientproperties.getmaxconnections(), httpclientproperties.getmaxconnectionsperroute(), httpclientproperties.gettimetolive(), httpclientproperties.gettimetoliveunit(), this.registrybuilder); this.connectionmanagertimer.schedule(new timertask() { public void run() { connectionmanager.closeexpiredconnections(); } }, 30000l, (long)httpclientproperties.getconnectiontimerrepeat()); return connectionmanager; } @bean public closeablehttpclient httpclient(apachehttpclientfactory httpclientfactory, httpclientconnectionmanager httpclientconnectionmanager, feignhttpclientproperties httpclientproperties) { requestconfig defaultrequestconfig = requestconfig.custom().setconnecttimeout(httpclientproperties.getconnectiontimeout()).setredirectsenabled(httpclientproperties.isfollowredirects()).build(); this.httpclient = httpclientfactory.createbuilder().setconnectionmanager(httpclientconnectionmanager).setdefaultrequestconfig(defaultrequestconfig).build(); return this.httpclient; } @bean @conditionalonmissingbean({client.class}) public client feignclient(httpclient httpclient) { return new apachehttpclient(httpclient); } @predestroy public void destroy() throws exception { this.connectionmanagertimer.cancel(); if (this.httpclient != null) { this.httpclient.close(); } } }
从代码@conditionalonclass({apachehttpclient.class})注解可知,只需要在pom文件上加上httpclient依赖即可。另外需要在配置文件中配置feign.httpclient.enabled为true,从@conditionalonproperty注解可知,这个配置可以不写,因为在默认情况下就为true:
<dependency> <groupid>io.github.openfeign</groupid> <artifactid>feign-httpclient</artifactid> <version>9.4.0</version> </dependency>
使用okhttp
查看feignautoconfiguration.httpclientfeignconfiguration的源码:
@configuration @conditionalonclass({okhttpclient.class}) @conditionalonmissingclass({"com.netflix.loadbalancer.iloadbalancer"}) @conditionalonmissingbean({okhttp3.okhttpclient.class}) @conditionalonproperty({"feign.okhttp.enabled"}) protected static class okhttpfeignconfiguration { private okhttp3.okhttpclient okhttpclient; protected okhttpfeignconfiguration() { } @bean @conditionalonmissingbean({connectionpool.class}) public connectionpool httpclientconnectionpool(feignhttpclientproperties httpclientproperties, okhttpclientconnectionpoolfactory connectionpoolfactory) { integer maxtotalconnections = httpclientproperties.getmaxconnections(); long timetolive = httpclientproperties.gettimetolive(); timeunit ttlunit = httpclientproperties.gettimetoliveunit(); return connectionpoolfactory.create(maxtotalconnections, timetolive, ttlunit); } @bean public okhttp3.okhttpclient client(okhttpclientfactory httpclientfactory, connectionpool connectionpool, feignhttpclientproperties httpclientproperties) { boolean followredirects = httpclientproperties.isfollowredirects(); integer connecttimeout = httpclientproperties.getconnectiontimeout(); boolean disablesslvalidation = httpclientproperties.isdisablesslvalidation(); this.okhttpclient = httpclientfactory.createbuilder(disablesslvalidation).connecttimeout((long)connecttimeout, timeunit.milliseconds).followredirects(followredirects).connectionpool(connectionpool).build(); return this.okhttpclient; } @predestroy public void destroy() { if (this.okhttpclient != null) { this.okhttpclient.dispatcher().executorservice().shutdown(); this.okhttpclient.connectionpool().evictall(); } } @bean @conditionalonmissingbean({client.class}) public client feignclient(okhttp3.okhttpclient client) { return new okhttpclient(client); } }
同理,如果想要在feign中使用okhttp作为网络请求框架,则只需要在pom文件中加上feign-okhttp的依赖,代码如下:
<dependency> <groupid>io.github.openfeign</groupid> <artifactid>feign-okhttp</artifactid> <version>10.2.0</version> </dependency>
openfeign替换为okhttp
pom中引入feign-okhttp
<dependency> <groupid>io.github.openfeign</groupid> <artifactid>feign-okhttp</artifactid> </dependency>
在application.yml中配置okhttp
feign: httpclient: connection-timeout: 2000 #单位ms,默认2000 max-connections: 200 #线程池最大连接数 okhttp: enabled: true
经过上面设置已经可以使用okhttp了,因为在feignautoconfiguration中已实现自动装配
如果需要对okhttp做更精细的参数设置,那需要自定义okhttp的实现,可以模仿上图中的实现
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
上一篇: JS学习笔记(一)
下一篇: Python是怎么操作文件和目录的?
推荐阅读
-
Feign 使用HttpClient和OkHttp方式
-
php foreach()使用方式和扩展实例汇总
-
android使用OkHttp实现下载的进度监听和断点续传
-
android使用OkHttp实现下载的进度监听和断点续传
-
详解在React.js中使用PureComponent的重要性和使用方式
-
网站关键词挖掘工具和正确使用方式
-
Volley源码之使用方式和使用场景详解
-
微信小程序授权 获取用户的openid和session_key【后端使用java语言编写】,我写的是get方式,目的是测试能否获取到微信服务器中的数据,后期我会写上post请求方式。
-
Python中星号的本质和使用方式
-
php使用redis的几种常见操作方式和用法示例