1. 程式人生 > >springcloud 之 Feign Rpc

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>>(){}