日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
OpenFeign的9個(gè)坑,每個(gè)都能讓你的系統(tǒng)奔潰

[[412891]]

目前成都創(chuàng)新互聯(lián)公司已為千余家的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站托管運(yùn)營(yíng)、企業(yè)網(wǎng)站設(shè)計(jì)、子長(zhǎng)網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

本文轉(zhuǎn)載自微信公眾號(hào)「程序員jinjunzhu」,作者jinjunzhu。轉(zhuǎn)載本文請(qǐng)聯(lián)系程序員jinjunzhu公眾號(hào)。

OpenFeign是SpringCloud中的重要組件,它是一種聲明式的HTTP客戶端。使用OpenFeign調(diào)用遠(yuǎn)程服務(wù)就像調(diào)用本地方法一樣,但是如果使用不當(dāng),很容易踩到坑。

坑一:用對(duì)Http Client

1.1 feign中http client

如果不做特殊配置,OpenFeign默認(rèn)使用jdk自帶的HttpURLConnection,我們知道HttpURLConnection沒有連接池、性能和效率比較低,如果采用默認(rèn),很可能會(huì)遇到性能問題導(dǎo)致系統(tǒng)故障。

可以采用Apache HttpClient,properties文件中增加下面配置:

 
 
 
 
  1. feign.httpclient.enabled=true 

pom文件中增加依賴:

 
 
 
 
  1.  
  2.     io.github.openfeign 
  3.     feign-httpclient 
  4.     9.3.1 
  5.  

也可以采用OkHttpClient,properties文件中增加下面配置:

 
 
 
 
  1. feign.okhttp.enabled=true 

pom文件中增加依賴:

 
 
 
 
  1.  
  2.     io.github.openfeign 
  3.     feign-okhttp 
  4.     10.2.0 
  5.  

1.2 ribbon中的Http Client

通過OpenFeign作為注冊(cè)中心的客戶端時(shí),默認(rèn)使用Ribbon做負(fù)載均衡,Ribbon默認(rèn)也是用jdk自帶的HttpURLConnection,需要給Ribbon也設(shè)置一個(gè)Http client,比如使用okhttp,在properties文件中增加下面配置:

 
 
 
 
  1. ribbon.okhttp.enabled=true 

坑二:全局超時(shí)時(shí)間

OpenFeign可以設(shè)置超時(shí)時(shí)間,簡(jiǎn)單粗暴,設(shè)置一個(gè)全局的超時(shí)時(shí)間,如下:

 
 
 
 
  1. feign.client.config.default.connectTimeout=2000 
  2. feign.client.config.default.readTimeout=60000 

如果不配置超時(shí)時(shí)間,默認(rèn)是連接超時(shí)10s,讀超時(shí)60s,在源碼feign.Request的內(nèi)部類Options中定義。

這個(gè)接口設(shè)置了最大的readTimeout是60s,這個(gè)時(shí)間必須大于調(diào)用的所有外部接口的readTimeout,否則處理時(shí)間大于readTimeout的接口就會(huì)調(diào)用失敗。

如下圖,在一個(gè)系統(tǒng)中使用OpenFeign調(diào)用外部三個(gè)服務(wù),每個(gè)服務(wù)提供兩個(gè)接口,其中serviceC的一個(gè)接口需要60才能返回,那上面的readTimeout必須設(shè)置成60s。

但是如果serviceA出故障了,表現(xiàn)是接口1超過60s才能返回,這樣OpenFeign只能等到讀超時(shí),如果調(diào)用這個(gè)接口的并發(fā)量很高,會(huì)大量占用連接資源直到資源耗盡系統(tǒng)奔潰。要防止這樣的故障發(fā)生,就必須保證接口1能fail-fast。最好的做法就是給serviceC單獨(dú)設(shè)置超時(shí)時(shí)間。

坑三:?jiǎn)畏?wù)設(shè)置超時(shí)時(shí)間

從上一節(jié)的講解我們看到,需要對(duì)serviceC單獨(dú)設(shè)置一個(gè)超時(shí)時(shí)間,代碼如下:

 
 
 
 
  1. feign.client.config.serviceC.connectTimeout=2000 
  2. feign.client.config.serviceC.readTimeout=60000 

這個(gè)時(shí)間會(huì)覆蓋第一節(jié)中默認(rèn)的超時(shí)時(shí)間。但是問題又來了,serviceC中又掉了serviceD,因?yàn)閟erviceD的故障導(dǎo)致接口6發(fā)生了讀超時(shí)的情況,為了不讓系統(tǒng)奔潰,不得不對(duì)serviceC的接口5單獨(dú)設(shè)置超時(shí)時(shí)間。如下圖:

坑四:熔斷超時(shí)時(shí)間

怎樣給單個(gè)接口設(shè)置超時(shí)時(shí)間,查看網(wǎng)上資料,必須開啟熔斷,配置如下:

 
 
 
 
  1. feign.hystrix.enabled=true 

開啟熔斷后,就可以給單個(gè)接口配置超時(shí)了。如果調(diào)用serviceC的接口5的聲明如下:

 
 
 
 
  1. @FeignClient(value = "serviceC"configuration = FeignMultipartSupportConfig.class) 
  2. public interface ServiceCClient { 
  3.     @GetMapping("/interface5") 
  4.     String interface5(String param); 

根據(jù)上面interface5接口的聲明,在properties文件中增加如下配置:

 
 
 
 
  1. hystrix.command.ServiceCClient#interface5(param).execution.isolation.thread.timeoutInMilliseconds=60000 

網(wǎng)上資料說的并不準(zhǔn)確,這個(gè)超時(shí)時(shí)間并沒有起作用。為什么不生效呢?

4.1 使用feign超時(shí)

最終使用的超時(shí)時(shí)間來自于Options類。如果我們配置了feign的超時(shí)時(shí)間,會(huì)選擇使用feign超時(shí)時(shí)間,下面代碼在FeignClientFactoryBean類的configureUsingProperties方法:

 
 
 
 
  1. if (config.getConnectTimeout() != null && config.getReadTimeout() != null) { 
  2.  builder.options(new Request.Options(config.getConnectTimeout(), config.getReadTimeout())); 

4.2 使用ribbon超時(shí)

如果沒有配置feign,但是配置了ribbon的超時(shí)時(shí)間,會(huì)使用ribbon的超時(shí)時(shí)間。我們看下這段源代碼,F(xiàn)eignLoadBalancer里面的execute方法,

 
 
 
 
  1. public RibbonResponse execute(RibbonRequest request, IClientConfig configOverride) 
  2.   throws IOException { 
  3.  Request.Options options; 
  4.  if (configOverride != null) { 
  5.   RibbonProperties override = RibbonProperties.from(configOverride); 
  6.   options = new Request.Options( 
  7.     override.connectTimeout(this.connectTimeout), 
  8.     override.readTimeout(this.readTimeout)); 
  9.  } 
  10.  else { 
  11.   options = new Request.Options(this.connectTimeout, this.readTimeout); 
  12.  } 
  13.  //這個(gè)request里面的client就是OkHttpClient 
  14.  Response response = request.client().execute(request.toRequest(), options); 
  15.  return new RibbonResponse(request.getUri(), response); 

4.3 使用自定義Options

對(duì)于單個(gè)接口怎么配置超時(shí)時(shí)間,我這里給出一個(gè)方案,如果你有其他方案,歡迎探討。我的方案是使用RestTemplate來調(diào)這個(gè)接口,單獨(dú)配置超時(shí)時(shí)間,配置代碼如下,這里使用OkHttpClient:

 
 
 
 
  1. public class RestTemplateConfiguration { 
  2.   
  3.     @Bean 
  4.     public OkHttp3ClientHttpRequestFactory okHttp3RequestFactory(){ 
  5.         OkHttp3ClientHttpRequestFactory requestFactory = new OkHttp3ClientHttpRequestFactory(); 
  6.         requestFactory.setConnectTimeout(2000); 
  7.         requestFactory.setReadTimeout(60000); 
  8.         return requestFactory; 
  9.     } 
  10.   
  11.     @Bean 
  12.     @LoadBalanced 
  13.     public RestTemplate restTemplate(OkHttp3ClientHttpRequestFactory okHttp3RequestFactory){ 
  14.         return new RestTemplate(okHttp3RequestFactory); 
  15.     } 

為了使用ribbon負(fù)載均衡,上面加了@LoadBalanced

如果使用RestTemplate,就會(huì)使用OkHttp3ClientHttpRequestFactory中配置的時(shí)間。

坑五:ribbon超時(shí)時(shí)間

作為負(fù)載均衡,ribbon超時(shí)時(shí)間也是可以配置的,可以在properties增加下面配置:

 
 
 
 
  1. ribbon.ConnectTimeout=2000 
  2. ribbon.ReadTimeout=11000 

有文章講ribbon配置的超時(shí)時(shí)間必須要滿足接口響應(yīng)時(shí)間,其實(shí)不然,配置feign的超時(shí)時(shí)間就足夠了,因?yàn)樗梢愿采w掉ribbon的超時(shí)時(shí)間。

坑六:重試默認(rèn)不開啟

OpenFeign默認(rèn)是不支持重試的,可以在源代碼FeignClientsConfiguration中feignRetryer中看出。

 
 
 
 
  1. @Bean 
  2. @ConditionalOnMissingBean 
  3. public Retryer feignRetryer() { 
  4.  return Retryer.NEVER_RETRY; 

要開啟重試,我們可以自定義Retryer,比如下面這行代碼:

 
 
 
 
  1. Retryer retryer = new Retryer.Default(100, 1000, 2); 

表示每間隔100ms,最大間隔1000ms重試一次,最大重試次數(shù)是1,因?yàn)榈谌齻€(gè)參數(shù)包含了第一次請(qǐng)求。

坑七:Ribbon重試

7.1 拉取服務(wù)列表

Ribbon默認(rèn)從服務(wù)端拉取列表的時(shí)間間隔是30s,這個(gè)對(duì)優(yōu)雅發(fā)布很不友好,一般我們會(huì)把這個(gè)時(shí)間改短,如下改成3s:

 
 
 
 
  1. serviceC.ribbon.ServerListRefreshInterval=3 

7.2 重試

Ribbon重試有不少需要注意的地方,這里分享4個(gè)。

1.同一實(shí)例最大重試次數(shù),不包括首次調(diào)用,配置如下:

 
 
 
 
  1. serviceC.ribbon.MaxAutoRetries=1 

這個(gè)次數(shù)不包括首次調(diào)用,配置了1,重試策略會(huì)先嘗試在失敗的實(shí)例上重試一次,如果失敗,請(qǐng)求下一個(gè)實(shí)例。

2.同一個(gè)服務(wù)其他實(shí)例的最大重試次數(shù),這里不包括第一次調(diào)用的實(shí)例。默認(rèn)值為1:

 
 
 
 
  1. serviceC.ribbon.MaxAutoRetriesNextServer=1 

3.是否對(duì)所有操作都重試,如果改為true,則對(duì)所有操作請(qǐng)求都進(jìn)行重試,包括post,建議采用默認(rèn)配置false。

 
 
 
 
  1. serviceC.ribbon.OkToRetryOnAllOperations=false 

4.對(duì)指定的http狀態(tài)碼進(jìn)行重試

 
 
 
 
  1. serviceC.retryableStatusCodes=404,408,502,500 

坑八:hystrix超時(shí)

如下圖:

hystrix默認(rèn)不開啟,但是如果開啟了hystrix,因?yàn)閔ystrix是在Ribbon外面,所以超時(shí)時(shí)間需要符合下面規(guī)則:hystrix超時(shí) >= (MaxAutoRetries + 1) * (ribbon ConnectTimeout + ribbon ReadTimeout)

如果Ribbon不重試,MaxAutoRetries=0

根據(jù)上面公式,假如我們配置熔斷超時(shí)時(shí)間如下:

 
 
 
 
  1. hystrix.command.ServiceCClient#interface5(param).execution.isolation.thread.timeoutInMilliseconds=15000 
  2. ribbon.ReadTimeout=8000 

這個(gè)配置是不會(huì)重試一次的。serviceA調(diào)用serviceB時(shí),hystrix會(huì)等待Ribbon返回的結(jié)果,如果Ribbon配置了重試,hystrix會(huì)一直等待直到超時(shí)。上面的配置,因?yàn)榈谝淮握?qǐng)求已經(jīng)耗去了8s,剩下時(shí)間7s不夠請(qǐng)求一次了,所以是不會(huì)進(jìn)行重試的。

坑九:使用OpenFeign做http客戶端

即使不用注冊(cè)中心,使用OpenFeign做普通http客戶端也是很方便的,但是有三點(diǎn)需要注意:

  • 不用配置ribbon相關(guān)參數(shù)
  • 使用RestTemplate調(diào)用時(shí),不考慮負(fù)載均衡
  • 使用過程中OpenFeign要組裝出自己的一套請(qǐng)求,跟直接使用http客戶端比,會(huì)有一定開銷
  • 使用OpenFeign有很多配置上的坑,對(duì)于沒有注冊(cè)中心的情況,建議直接使用http客戶端

 


當(dāng)前題目:OpenFeign的9個(gè)坑,每個(gè)都能讓你的系統(tǒng)奔潰
文章鏈接:http://www.5511xx.com/article/cdghgji.html