Spring Cloud Gateway基於Spring Boot 2,是Spring Cloud的全新專案,該專案提供了一個構建在Spring 生態之上的API閘道器。本文基於的Spring Cloud版本為Finchley M9
,Spring Cloud Gateway對應的版本為2.0.0.RC1
。
Spring Cloud Gateway入門一文介紹了全新的Spring Cloud Gateway的一些基礎應用。本文將會介紹Spring Cloud Gateway重試過濾器。
過濾器
GatewayFilter
閘道器過濾器用於攔截和鏈式處理web請求,可以實現橫切的、與應用無關的需求,比如安全、訪問超時的設定等等。
public interface GatewayFilter {
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
複製程式碼
介面中定義了唯一的方法#filter
,處理web請求,並且可以通過給定的過濾器鏈傳遞到下一個過濾器。該介面有多個實現類,下面看一下該介面的類圖。
GatewayFilter
有兩個實現類,但是在原始碼中尋找該介面的用法會發現,在GatewayFilterFactory
實現類中有內部匿名類,實際是返回了一個 GatewayFilter
內部實現類。
Spring Cloud Gateway提供了很多種類的過濾器工廠,閘道器過濾器有近二十個實現類,總得說來可以分為七類:Header、Parameter、Path、Status、Redirect跳轉、Hystrix熔斷和RateLimiter限流等。
重試過濾器
請求的重試
當轉發到代理服務時,遇到指定的服務端Error,如httpStatus為500時,我們可以設定重試幾次。除了對指定的異常重試之外,還可以指定請求的方法,GET或POST。
實驗場景涉及到:閘道器服務和使用者服務。客戶端請求經過閘道器,請求使用者服務的API介面,遇到指定的異常時,進行重試。
專案準備
示例啟動兩個服務:Gateway-Server和user-Server。模擬的場景是,客戶端請求後端服務,閘道器提供後端服務的統一入口。後端的服務都註冊到服務發現Consul(搭建zk,Eureka都可以,筆者比較習慣使用consul)。閘道器通過負載均衡轉發到具體的後端服務。
使用者服務
使用者服務註冊到Consul上,並提供一個介面/test。
閘道器服務
引入閘道器的依賴,並進行相應配置。上一章已經講過,這裡不重複列出程式碼,具體見原始碼。
服務改造
閘道器服務
閘道器服務中,新增一個路由的定義retry_java
,請求的判定是路徑以/test
為字首的請求,並將請求轉發到user服務。當遇到內部服務錯誤(狀態碼為500)時,設定重試的次數為2。當然該路由也可以通過閘道器服務的配置檔案,效果是一樣的。
@Bean
public RouteLocator retryRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("retry_java", r -> r.path("/test/**")
.filters(f -> f.stripPrefix(1)
.retry(config -> config.setRetries(2).setStatuses(HttpStatus.INTERNAL_SERVER_ERROR)))
.uri("lb://user"))
.build();
}
複製程式碼
使用者服務
使用者服務增加一個API介面,請求中傳入引數key和count。
ConcurrentHashMap<String, AtomicInteger> map = new ConcurrentHashMap<>();
@GetMapping("/exception")
public String testException(@RequestParam("key") String key, @RequestParam(name = "count", defaultValue = "3") int count) {
AtomicInteger num = map.computeIfAbsent(key, s -> new AtomicInteger());
int i = num.incrementAndGet();
log.warn("Retry count: "+i);
if (i < count) {
throw new RuntimeException("temporarily broken");
}
return String.valueOf(i);
}
複製程式碼
這裡主要是為了能配置閘道器請求次數的演示,count是指定的重試次數,預設為3,第一次和第二次都會丟擲執行時異常(狀態碼為500),變數 i 是key對應的值,初始為0,每重試一次,i 會遞增,直到 i 大於等於count的值。
測試結果
根據上面的實現,我們訪問的地址為http://localhost:9090/test/exception?key=abc&count=2
。
按照使用者服務實現的邏輯,使用者服務將會重試一次即可成功。使用者服務的控制檯日誌資訊如下:
Retry count: 1
java.lang.IllegalArgumentException: temporarily broken] with root cause
...
Retry count: 2
複製程式碼
控制檯的資訊和最後的響應結果可以看出,請求的重試執行成功。
小結
本文在Spring Cloud Gateway入門的基礎上,介紹了Spring Cloud Gateway的過濾器相關概念,並具體介紹了其中的一個過濾器工廠:RetryGatewayFilterFactory
。當轉發到代理服務時,遇到指定的服務端Error,如httpStatus為500時,我們可以設定重試幾次,應用重試過濾器。Spring Cloud Gateway提供了很多過濾器工廠的實現,後面文章將會介紹其中比較重要的過濾器,敬請關注。
原始碼地址
https://github.com/keets2012/Spring-Cloud_Samples
訂閱最新文章,歡迎關注我的公眾號
參考
Spring Cloud Gateway官方文件