springcloud 之 Feign Rpc
既然springcloud是一個微服務架構生態體系,而且上一章我們也介紹了 微服務體系中一個核心元件“服務的發現與註冊”eureka,接下來我們來簡單探索以下微服務體系中另一個核心元件“rpc”;在springcloud體系中實現rpc的元件有2個,一個是ribbon,另一個是feign,而且feign在底層封裝了ribbon,以更友好,更靈活的形式展現在了我們眼前,所以今天我們研究的重心放在了feign身上。
(摘抄一段話,幫助大家更清晰的認識feign)
feign是netflix提供的服務間基於http的rpc呼叫框架,在spring cloud得到廣泛應用。預設情況下,一個feign client是在hystrix斷路器中執行,並利用ribbon進行軟負載選擇遠端服務(service),所以可以想象出一個feign client的層次架構是包裹的層次,hystrix控制整個rpc從呼叫到方法返回,而ribbon控制從選址到socket返回;
那麼什麼是hystrix呢?
首先我們先置身於這樣一個場景在微服務架構中,我們將業務拆分成一個個的服務,而服務與服務之間可以相互呼叫(RPC方式)。為了保證其高可用,單個服務又可能回事叢集環境部署。所以可能存在由於網路原因或者自身的原因,並不能保證服務的100%可用,如果單個服務出現問題,呼叫這個服務就會出現網路延遲,此時若有大量的網路湧入,會形成任務累計,導致服務癱瘓,甚至導致服務“雪崩”。
為了解決這個問題,就出現斷路器模型。
而hystrix就是Netflix的一個庫並且實現了斷路器模式。
(摘抄自一位網友的圖)
較底層的服務如果出現故障,會導致連鎖故障。當對特定的服務的呼叫達到一個閥值(hystric 是5秒20次) 斷路器將會被開啟。
斷路開啟後,可用避免連鎖故障,fallback方法可以直接返回一個固定值。
好了,接下來我們來配置一下實際環境中我們應該怎樣使用feign + hystrix?
注:基於test專案(我新建的另一個springboot專案)和demo-springboot專案;
1.開啟test專案的pom.xml加入相關依賴:
<!--feign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId><version>1.3.4.RELEASE</version> </dependency>
2.開啟application-dev.properties加入以下內容:
#feign read timeout(10s) hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000 #feign read timout disable(該配置,用於禁用Hystrix的超時時間) #hystrix.command.default.execution.timeout.enabled=false #關閉hystrix功能 #feign.hystrix.enabled=false
切記feign read timeout配置一個合適的超時時間,不要用預設的,我剛開始的時候沒有配置,結構一直呼叫返回error,發現是超時了。
3.在demo-springboot中新增測試controller:
package com.example.demo.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * @author xiaofeng * @version V1.0 * @title: TestController.java * @package: com.example.demo.controller * @description: TODO * @date 2018/4/3 0003 下午 2:10 */ @RestController @RequestMapping(value = "/test") public class TestController { @RequestMapping(value = "/info") public String info(@RequestParam(value = "msg") String msg) { return "welcome to demo-springboot: " + msg; } }
4.在test專案中增加rpc相關服務類:
@FeignClient(value = "demo-springboot", fallback = RpcServiceImpl.class) public interface RpcService { /** * 查詢test * * @param msg * @return */ @RequestMapping(value = "/test/info", method = RequestMethod.GET) String query(@RequestParam(value = "msg") String msg); }
@Service public class RpcServiceImpl implements RpcService { /** * 查詢test * * @param msg * @return */ @Override public String query(String msg) { return "error"; } }
5.在test專案中編寫測試controller:
@RestController public class TestController { @Autowired RpcService rpcService; @RequestMapping(value = "/test/index") public String index(@RequestParam(value = "msg") String msg) { return rpcService.query(msg); } }
然後再啟動類中開啟註解@EnableFeignClients(basePackages = {"com.xx.xx.test.service"}):表示feign 需要掃描的package路徑(我的rpcService放在service包下)。
@EnableFeignClients(basePackages = {"com.xx.xx.test.service"}) @EnableAutoConfiguration @EnableEurekaClient @SpringBootApplication public class Xsignal2TestApplication { public static void main(String[] args) { SpringApplication.run(Xsignal2TestApplication.class, args); } }
6.最後分別啟動discover-server、demo-springboot、test三個服務
檢視eureka控制面板三個服務是否都已經啟動:
ok,接下來開始測試,首先是正常測試,開啟瀏覽器:
出現的是我們理想的結果,說明我們的rpc已經走通了哦,是不是有點小雞凍啊。
7.介紹一些常用配置
以上這種配置也是全域性配置,如果我們想針對某一個介面配置,比如/hello介面,那麼可以按照下面這種寫法,如下:
# 設定熔斷超時時間
hystrix.command.hello.execution.isolation.thread.timeoutInMilliseconds=10000
# 關閉熔斷功能
hystrix.command.hello.execution.timeout.enabled=false
# 配置請求GZIP壓縮
feign.compression.request.enabled=true
# 配置響應GZIP壓縮
feign.compression.response.enabled=true
# 配置壓縮支援的MIME TYPE
feign.compression.request.mime-types=text/xml,application/xml,application/json
# 配置壓縮資料大小的下限
feign.compression.request.min-request-size=2048
注意點:
1.有些公共的元件抽出來其他模組的maven依賴,此時要在使用的專案中載入此jar包的spring component以及feign元件,僅僅依靠@ComponentScan是不夠的,還需要在@EnableFeignClients(basePackages = {"com.xx.xx.test.service"})中標註basekPackages。
2.springcloud feign 注入bean null問題
解決辦法:
1. 如果swagger版本是v1.x,那麼請參考:https://segmentfault.com/a/1190000006595187
2. 如果swagger版本是v2.x,那麼請將升級swagger版本到2.5.0以上即可。
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.5.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.5.0</version> </dependency>3.feign rpc返回的json物件轉換失敗1.複雜物件轉換失敗(Response<pageList<obj>)
2.介面返回物件轉換:
ResponseModel<Long> responseModel = JsonUtils.json2Obj(data, new TypeReference<ResponseModel<Long>>(){});
new TypeReference<ResponseModel<Long>>(){}