「微服務(wù)設(shè)計之禪」限流模式
前言
微服務(wù)本質(zhì)上分布式架構(gòu),當(dāng)我們使用分布式系統(tǒng)時任何不可預(yù)知的問題都會發(fā)生(例如網(wǎng)絡(luò)可用性問題、服務(wù)可用性問題、中間件可用性問題)。一個系統(tǒng)的問題可能會直接影響另外一個系統(tǒng)的使用或性能。所以在系統(tǒng)設(shè)計過程既要保證自身運行的彈性需求,也要避免對下游服務(wù)級聯(lián)故障。
限流模式
在微服務(wù)技術(shù)架構(gòu)中,當(dāng)有多個服務(wù)(A,B,C, D)時,一個服務(wù)(A)可能依賴于另一服務(wù)(B),而另一服務(wù)(B)又可能依賴于 C,依此類推。
如下圖我們有 2 個服務(wù) A 和 B,B 服務(wù)要進行大量的業(yè)務(wù)計算和其他依賴接口調(diào)用導(dǎo)致 B 的最大請求處理個數(shù)小于請求 A 的并發(fā)數(shù)。

當(dāng)服務(wù) A 接收到很多的服務(wù)請求時,由于 B 服務(wù)能夠處理的請求數(shù)量多,從而導(dǎo)致服務(wù)宕機。
作為服務(wù) B 為了保證自身高,通過拒絕無法處理的請求來保證服務(wù)正常運行。

限流模式通過限制在指定時間窗內(nèi)運行的請求處理數(shù)量,幫助提升服務(wù)的可用性。
示例程序
架構(gòu)圖

如上圖所示,簡單模擬電商下單邏輯
用戶登錄瀏覽商品 (商品庫存模塊) 扣減商品庫存 (商品庫存模塊) 創(chuàng)建商品訂單 (訂單模塊)
product-service 通過調(diào)用 order-service 服務(wù)下單
代碼實現(xiàn)
├──?ratelimiter-demo
???├──?order-service????????#訂單服務(wù)??(8070)
???└──?product-service??????#商品庫存服務(wù)??(8050)
依賴說明。由于 hystrix 年久失修,這里使用 resilience4j 斷路保護器做演示
<dependency>
????<groupId>io.github.resilience4jgroupId>
????<artifactId>resilience4j-spring-boot2artifactId>
????<version>1.6.1version>
dependency>
針對接口定義重試策略 10s 內(nèi)最多允許通過 5 個請求
resilience4j.ratelimiter:
??instances:
????createOrder:
??????limitForPeriod:?5????????#?最多運行多少個
??????limitRefreshPeriod:?10s??#時間窗限制?10s
消費方接口。product-service 8050
/**
?*?用戶點擊購買
?*/
@SneakyThrows
@GetMapping("/order")
public?String?buy()?{
????//?模擬調(diào)用?訂單服務(wù)下單
????orderService.createOrder().get();
????return?"success";
}
定義遠(yuǎn)程調(diào)用類使用 Retry 包裝
/**
?*?創(chuàng)建訂單
?*?name:?指定接口限流配置名稱
?*?fallbackMethod:?限流后降級方法
?*/
@RateLimiter(name?=?"createOrder",?fallbackMethod?=?"getError")
public?CompletableFuture?createOrder()? {
????return?CompletableFuture.supplyAsync(()?->?restTemplate.getForEntity("http://localhost:8070/createOrder"
????????????,?String.class).getBody());
}
public?CompletableFuture?getError(Throwable?error)? {
????log.warn("創(chuàng)建訂單失敗了?{}",?error.getMessage());
????throw?new?RuntimeException("創(chuàng)建訂單失敗了");
}
服務(wù)提供方。order-service 8070
@RestController
public?class?PayController?{
????@SneakyThrows
????@GetMapping("/createOrder")
????public?String?createOrder()?{
????????return?"創(chuàng)建訂單服務(wù)";
????}
}
開始測試
并發(fā) 10 個線程,請求商品服務(wù) (由于我們設(shè)置策略 10 秒內(nèi)只允許 5 個請求)


訂單服務(wù)日志,由于是第一次請求觸發(fā)異常,然后服務(wù)調(diào)用方自動重試產(chǎn)生第二次調(diào)用。
2020-12-07?15:53:46.698??WARN?52265?---?[nio-8050-exec-6]?c.example.product.service.OrderService???:?創(chuàng)建訂單失敗了?RateLimiter?'createOrder'?does?not?permit?further?calls
...?異常日志?...
源碼:https://github.com/lltx/microservices-pattern
參考資料和部分圖片來源 https://www.vinsguru.com
往期推薦
