Spring Cloud Gateway(續)

本文主要介紹 Spring Cloud Gateway 的路由熔斷、路由重試和高可用。

路由熔斷

在前面學習 Hystrix 的時候,我們知道 Hystrix 有服務降級的能力,即如果服務調用出現了異常,則執行指定的 fallback 方法。Spring Cloud Gateway 也融合了 Hystrix,可以爲我們提供路由層面服務降級。我們就來看看如何來做。

在之前 gateway 工程的基礎上引入 Hystrix 依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

配置文件添加 Filter

spring:
  cloud:
    gateway:
      routes:
      - id: service_customer
        uri: lb://CONSUMER
        predicates:
        - Path=/customer/**
        filters:
        - name: Hystrix
          args:
            name: fallbackcmd
            fallbackUri: forward:/fallback

Hystrix 支持兩個參數:

  • name:即HystrixCommand的名字
  • fallbackUri:即 fallback 對應的 uri,這裏的 uri 僅支持forward: schemed 的

最後在 gateway 的項目中創建一個 endpoint:/fallback

@RestController
public class FallbackController {

    @GetMapping("/fallback")
    public String fallback() {
        return "Hello World!\nfrom gateway";
    }

}

僅做以上配置就 OK 了,如果需要更強大的功能,可以參考HystrixGatewayFilterFactory進行自定義。

路由重試

雖然目前官方文檔上還沒有關於重試的內容,不過我們能在代碼中找到RetryGatewayFilterFactory。但是據我測試這個好像還是有些問題。

理論上只要在 application.xml 裏這麼配置就可以了

spring:
  cloud:
    gateway:
      routes:
      - id: service_customer
        uri: lb://CONSUMER
        predicates:
        - Path=/customer/**
        filters:
        - Retry=5

爲了測試我們再改造一下 consumer 中的 HelloController,我們讓它在方法入口處打印 log,然後 sleep 10 分鐘

@CommonsLog
@RequestMapping("/hello")
@RestController
public class HelloController {

    @Autowired
    HelloRemote helloRemote;

    @GetMapping("/{name}")
    public String index(@PathVariable("name") String name) throws InterruptedException {
        log.info("the name is " + name);
        if ("retry".equals(name)) {
            TimeUnit.MINUTES.sleep(10);
        }
        return helloRemote.hello(name) + "\n" + new Date().toString();
    }

}

但是實際測試發現,當 Gateway 向 consumer 請求的時候,根本就沒有超時這個概念,我也沒找到能設置超時的地方。唯一能找到的一個超時是通過 Hystrix 設置(參考 github),比如上邊我們HystrixCommand的 name 是 fallbackcmd,那麼就設置如下

hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000

但是配置了 Hystrix 之後,超時就直接 fallback 了,所以根本輪不到 retry

java.lang.NullPointerException: null
	at org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory.lambda$null$0(RetryGatewayFilterFactory.java:55) ~[spring-cloud-gateway-core-2.0.0.RC1.jar:2.0.0.RC1]

那我 Hystrix 只配置 name 不配置 fallbackUri 行不行?也不行。

雖然這樣確實 retry 了,在 consumer 的 log 中能看到多條打印,但是在 gateway 裏邊卻報錯了

com.netflix.hystrix.exception.HystrixRuntimeException: fallbackcmd command executed multiple times - this is not permitted.

所以看樣子這個 Retry 現在還不能用,等有時間了再研究下。

高可用

我們實際使用 Spring Cloud Gateway 的方式如上圖,不同的客戶端使用不同的負載將請求分發到後端的 Gateway,Gateway 再通過 Eureka 調用後端服務,最後對外輸出。因此爲了保證 Gateway 的高可用性,前端可以同時啓動多個 Gateway 實例進行負載,在 Gateway 的前端使用 Nginx 或者 F5 進行負載轉發以達到高可用性。

參考

Spring Cloud Gatewa - Hystrix GatewayFilter Factory

示例代碼可以從 Github 獲取:https://github.com/zhaoyibo/spring-cloud-study

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章