一呼盆、什么是Feign
Feign是聲明式Web服務客戶端,它使編寫Web服務客戶端更加容易盾剩。Feign不做任何請求處理雷激,通過處理注解相關信息生成Request替蔬,并對調用返回的數(shù)據(jù)進行解碼,從而實現(xiàn)簡化HTTP API的開發(fā)屎暇。
二承桥、Feign和Openfeign的區(qū)別
Feign最早是由Netflix公司進行維護的,后來Netflix不再對其進行維護根悼,最終Feign由社區(qū)進行維護凶异,更名為Openfeign并將原項目遷移至新的倉庫。
Feign集成了Ribbon挤巡、RestTemplate實現(xiàn)了負載均衡的執(zhí)行Http調用剩彬,只不過對原有的方式(Ribbon+RestTemplate)進行了封裝,開發(fā)者不必手動使用RestTemplate調服務矿卑,而是定義一個接口喉恋,在這個接口中標注一個注解即可完成服務調用,這樣更加符合面向接口編程的宗旨母廷,簡化了開發(fā)轻黑。
三、常用負載均衡策略
隨機(Random)算法:在實例列表中隨機選擇某個實例琴昆。
輪詢(RoundRobin)算法:按順序選擇實例氓鄙。
最少連接數(shù)(Least Connections)算法:每次取連接數(shù)最少的實例。
一致性哈希(Consistent Hashing)算法:基于一致性哈希算法總是將相同參數(shù)的請求落在同一個實例上业舍。
權重隨機(Weigthd Random):隨機取一個數(shù)抖拦,根據(jù)這個數(shù)屬于哪個范圍選擇對應的實例。
四勤讽、Openfeign如何負載均衡
一般而言蟋座,我們生產者注冊多個服務拗踢,消費者調用時需要使用負載均衡從中選取一個健康并且可用的生產者服務脚牍。因為Openfeign內部集成Ribbon,所以也支持此特性巢墅。Openfeign默認的負載均衡策略是輪詢調用诸狭。
五、Ribbon負載均衡原理
我們以前接觸的nginx的負載均衡是服務端的負載均衡君纫,而Ribbon為客戶端提供負載均衡驯遇,其內部提供了一個負載均衡器ILoadBalance。
LoadBalancerClient在初始化的時候蓄髓,會通過ILoadBalance向Eureka注冊中心獲取服務注冊列表叉庐,并且每10s一次向EurekaClient發(fā)送“ping”,來判斷服務的可用性会喝,如果服務的可用性發(fā)生了改變或者服務數(shù)量和之前的不一致陡叠,則從注冊中心更新或者重新拉取玩郊。LoadBalancerClient有了這些服務注冊列表,就可以根據(jù)具體的IRule來進行負載均衡枉阵,來獲取調用的服務译红。
六、Ribbon負載均衡方式
6.1 隨機策略RandomRule
核心代碼:
int index = rand.nextInt(serverCount); // 使用jdk內部的Random類隨機獲取索引值index
server = upList.get(index); // 得到服務器實例
6.2 RoundRobinRule輪詢策略
表示每次都取下一個服務器兴溜,如果失敗會繼續(xù)向下嘗試獲取10次
6.3 WeightedResponseTimeRule加權策略
開始的時候還沒有權重列表侦厚,采用父類的輪詢方式,有一個默認每30秒更新一次權重列表的定時任務拙徽,該定時任務會根據(jù)實例的響應時間來更新權重列表刨沦,choose方法做的事情就是,用一個(0,1)的隨機double數(shù)乘以最大的權重得到randomWeight膘怕,然后遍歷權重列表已卷,找出第一個比randomWeight大的實例下標,然后返回該實例淳蔼。
6.4 BestAvailableRule策略用來選取最少并發(fā)量請求的服務器
七侧蘸、Openfeign更改負載均衡策略(默認輪詢)
7.1 方式一:使用已經(jīng)提供的
@Bean
public IRule ribbonRule() {
return new BestAvailableRule();//最小請求數(shù)
}
7.2 方式二:使用自定義的
通過底層源碼我們發(fā)現(xiàn),這些策略都繼承了AbstractLoadBalancerRule抽象類鹉梨,所以我們寫自定義負載均衡策略讳癌,只需要2步
第一步:編寫類繼承AbstractLoadBanlancerRule抽象類,實現(xiàn)choose方法存皂。
第二步:注入類實例
@Bean
public IRule ribbonRule() {
return new 自定義的類();//自定義負載策略類
}
八晌坤、Openfeign網(wǎng)絡通信方式
如果不做特殊配置,OpenFeign默認使用jdk自帶的HttpURLConnection旦袋,我們知道HttpURLConnection沒有連接池骤菠、性能和效率比較低,如果采用默認疤孕,很可能會遇到性能問題導致系統(tǒng)故障商乎。因此我們可以將其改為okhttp或者httpclient。
8.1 Feign中http client
8.1.1 Apache HttpClient
可以采用Apache HttpClient祭阀,properties文件中增加下面配置
feign.httpclient.enabled=true
pom文件中增加依賴
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>9.3.1</version>
</dependency>
8.1.2 OkHttpClient
也可以采用OkHttpClient鹉戚,properties文件中增加下面配置
feign.okhttp.enabled=true
pom文件中增加依賴
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>10.2.0</version>
</dependency>
8.2 Ribbon中的Http Client
通過OpenFeign作為注冊中心的客戶端時,默認使用Ribbon做負載均衡专控,Ribbon默認也是用jdk自帶的HttpURLConnection抹凳,需要給Ribbon也設置一個Http client,比如使用okhttp伦腐,在properties文件中增加下面配置赢底。
ribbon.okhttp.enabled=true
九、Openfeign日志級別
OpenFeign的日志級別有
NONE: 默認的,不顯示任何日志幸冻。
BASIC: 僅記錄請求方法嗅剖、URL、響應狀態(tài)碼以及執(zhí)行時間嘁扼。
HEADERS:除了BASIC 中自定義的信息外信粮,還有請求和響應的信息頭。
FULL: 除了HEADERS中定義的信息外趁啸, 還有請求和響應的正文以及元數(shù)據(jù)强缘。
自己寫一個配置類
@Configuration
public class OpenFeignLogConfig {
@Bean
Logger.Level feignLoggerLeave(){
return Logger.Level.FULL;
}
}
配置文件
logging:
level:
*[feign日志以什么級別監(jiān)控哪個接口]:
com.king.springcloud.service.OrderFeignService: debug
十、OpenFeign超時時間
10.1 全局超時時間
OpenFeign可以設置超時時間不傅,簡單粗暴旅掂,設置一個全局的超時時間,如下
feign.client.config.default.connectTimeout=2000
feign.client.config.default.readTimeout=60000
如果不配置超時時間访娶,默認是連接超時10s商虐,讀超時60s,在源碼feign.Request的內部類Options中定義崖疤。
10.2 單服務設置超時時間
需要對serviceC單獨設置一個超時時間秘车,代碼如下
feign.client.config.serviceC.connectTimeout=2000
feign.client.config.serviceC.readTimeout=60000
這個時間會覆蓋全局默認的超時時間。
十一劫哼、Ribbon超時時間
作為負載均衡叮趴,Ribbon超時時間也是可以配置的,可以在properties增加下面配置
ribbon.ConnectTimeout=2000
ribbon.ReadTimeout=11000
有文章講ribbon配置的超時時間必須要滿足接口響應時間权烧,其實不然眯亦,配置feign的超時時間就足夠了,因為它可以覆蓋掉ribbon的超時時間般码。
十二妻率、開啟熔斷
可以在properties增加下面配置
feign.hystrix.enabled=true
十三、開啟重試
13.1 OpenFeign開啟重試
OpenFeign默認是不支持重試的板祝,可以在源代碼FeignClientsConfiguration中feignRetryer中看出
@Bean
@ConditionalOnMissingBeanpublic
Retryer feignRetryer { return Retryer.NEVER_RETRY;}
要開啟重試宫静,我們可以自定義Retryer,比如下面這行代碼
Retryer retryer = new Retryer.Default(100, 1000, 2);
表示每間隔100ms扔字,最大間隔1000ms重試一次囊嘉,最大重試次數(shù)是1,因為第三個參數(shù)包含了第一次請求革为。
13.2 Ribbon重試
13.2.1 拉取服務列表
Ribbon默認從服務端拉取列表的時間間隔是30s,這個對優(yōu)雅發(fā)布很不友好舵鳞,一般我們會把這個時間改短震檩,如下改成3s
myService.ribbon.ServerListRefreshInterval=3
其中myService
是你的目的地微服務的名稱
13.2.2 重試
Ribbon重試有不少需要注意的地方,這里分享4個。
1抛虏、同一實例最大重試次數(shù)博其,不包括首次調用,配置如下
serviceC.ribbon.MaxAutoRetries=1
這個次數(shù)不包括首次調用迂猴,配置了1慕淡,重試策略會先嘗試在失敗的實例上重試一次,如果失敗沸毁,請求下一個實例峰髓。
2、同一個服務其他實例的最大重試次數(shù)息尺,這里不包括第一次調用的實例携兵。默認值為1
serviceC.ribbon.MaxAutoRetriesNextServer=1
3、是否對所有操作都重試搂誉,如果改為true徐紧,則對所有操作請求都進行重試,包括post,建議采用默認配置false
serviceC.ribbon.OkToRetryOnAllOperations=false
4炭懊、對指定的http狀態(tài)碼進行重試
serviceC.retryableStatusCodes=404,408,502,500
十四并级、使用OpenFeign做http客戶端
即使不用注冊中心,使用OpenFeign做普通http客戶端也是很方便的侮腹,但是有三點需要注意:
- 不用配置ribbon相關參數(shù)死遭。
- 使用RestTemplate調用時,不考慮負載均衡凯旋。
- 使用過程中OpenFeign要組裝出自己的一套請求呀潭,跟直接使用http客戶端比,會有一定開銷至非。