resilience4j不夠用?自制分散式斷路器來幫忙 -Nicolas
當服務的多個例項可以呼叫指定的外部服務,在這些服務例項中都要定製斷路策略很浪費,比如呼叫外部服務一段時間後進行關閉處理邏輯等。他們可以統一共享呼叫同一個外部服務的統計資訊,這樣一個呼叫失敗以後,其他服務例項就不要再重試一遍,這是使用分散式斷路器的地方。
由於找不到現有解決方案,我們決定自行嘗試一下。簡而言之,我們從ratelimitj的啟發中快速構建了一個分散式斷路器。通話統計資訊是使用Redis共享的,它就像一個超級按鈕。我們計劃將其開源,但這將是另一篇文章的主題;-) 這裡分享思路。
1. 共享的統計資訊:指標,跟蹤和監視
我們對指標的需求非常簡單:對於每個佇列和每種命令,我們都希望跟蹤,並瞭解其中有多少成功了,或失敗和重試或最終移入隔離區。這將使我們能夠了解流量並在需要時調整引數。
鑑於我們在Java / Kotlin應用程式中使用的是Spring Boot,因此這裡沒有做任何決定:我們將照常使用Micrometer來發布帶有適當標籤的量規,然後在Datadog中遵循這些指標,這是一個(好)監控SAAS。
2. 視覺化
儘管有日誌,指標和警報是很明顯的,但我們希望有一種方法可以隨時視覺化計劃或隔離的任務及其嘗試次數和任何可能的錯誤,以及採取行動來執行這些任務(刪除它們) ,重新安排時間,等等)。
3.總體設計思路:
第一個設計決策是關於如何表示命令,執行請求和隔離的。以下是做出的主要決定和最終決定:
- 命令是一塊程式碼,可以通過名稱找到,並且通過提供一個其(Java)的地圖的引數執行。由於我們使用的是Spring,因此命令是Spring元件,並且Spring上下文充當命令登錄檔。
- 命令執行請求包括一個命令的名稱和引數,例如:(名稱= pushTransactionForInvoice,ARGS = {invoiceId,的transactionId})
- 命令與“邏輯”佇列相關聯,每個佇列對應於一個外部服務。因此,該“邏輯”佇列是跟蹤呼叫並應用速率限制和斷路邏輯的單元。
- 計劃後,命令執行請求將作為任務儲存在PostgreSQL表(佇列表)中,並具有以下核心詳細資訊:任務ID,計劃執行日期/時間,“邏輯”佇列名稱,命令名稱,命令引數,命令重量(限制wrt速率,請參閱“演算法”部分)
- 還儲存了與命令的執行相關的其他詳細資訊:任務狀態(PENDING或LOCKED),到目前為止的執行次數,最新的執行錯誤(如果有)。
- 最後,儲存“ 下一個任務 s” 的列表,這些列表是僅在成功完成當前任務後才執行的命令。稍後對此有更多詳細資訊。
- 命令的引數和要執行的下一個任務的列表儲存為JSONB,以說明它們的可變性。
- 該隔離被表示為第二表,儲存幾乎快要任務,加上上次執行嘗試的時間相同的細節。
4.為指定服務配置新的命令佇列
//將請求定義為命令 放入佇列中 const val MY_QUEUE_NAME: String = "myServiceQueue" @Configuration class MyServiceQueueConfiguration { @Bean(MY_QUEUE_NAME) fun myServiceQueue(commandExecutionQueueFactory: CommandExecutionQueueFactory) = commandExecutionQueueFactory.createQueue( MY_QUEUE_NAME, // optionally redefine part or totality of the default policy DEFAULT_EXECUTION_POLICY.copy( concurrency = 4, delayBeforeConsideringTask = Duration.ofSeconds(5), maxRetriesBeforeQuarantine = 10, // optional, none by default rateLimits = RateLimits( 2300 executionsOver Duration.ofMinutes(15), 4500 executionsOver Duration.ofMinutes(30), 8800 executionsOver Duration.ofHours(1) ), // optional, none by default circuitBreaking = CircuitBreaking( failureRateThreshold = 0.5, windowDuration = Duration.ofMinutes(10), // will tell that some exceptions are to be considered as provider failures considerExceptionAsFailureIf = someExceptionPredicate() ) ), // optional, a probe that will be queried to know whether to pause task consumption // (may query a feature flag, a state defined via some UI, etc.) somePauseProbe() ) } |
將命令執行請求定義為一個簡單的物件,其中包含要執行的命令的名稱和一個(Java)引數對映。
5. 命令執行佇列的核心邏輯
class CommandQueue(...) { // ... override fun schedule(command: CommandSpecification) { // add task to queue, log details, emit metrics schedule(ScheduledTask( command, queueName, clock, // this is the important part for deduplication to work scheduledExecutionDate = executionPolicy.computeNextExecutionDate(clock, tries = 0) ), command.deduplicate) } // ... override fun processCommands(): Boolean { val circuitBreaker = circuitBreaker() if (circuitBreaker.isOpen()) { return false } val task = taskRepository.tryLockingTaskWithEarliestScheduleOlderThan(queueName, LocalDateTime.now(clock)) ?: return false val command = commandRegistry.get(task.commandName) // each case: decides what to do with task, log details, emit metrics val executionResult = when { command == null -> commandNotFound(task) violatesRateLimit(task.weight) -> rateLimited(task) !running -> aborted(task) else -> executeCommand(command, task) } registerCall(circuitBreaker, executionResult) // remove task, or move it to quarantine, or update number of tries handleExecutionResult(executionResult) return executionResult.commandExecuted } // ... } |
6.缺陷
輪詢PostgreSQL表也不是一個好主意。但是,每個“邏輯”佇列每秒最多隻能輪詢一次。
談到佇列,它們都在同一張表中進行管理,考慮到更多的使用情況,這可能是效能問題。如果發生這種情況,我們可以將表專用於每個佇列,而當要新增佇列時,我們需要付出更多配置的代價(現在我們需要建立表)。
我們系統的一個更實際的限制是它目前僅處理同步操作,但是我們可以對其進行調整,以便以非同步方式接收命令執行的結果。
更多點選標題見原文
相關文章
- Excel不夠用? Smartbi NLA對話式分析來幫你Excel
- 使用Resilience4j實施反應式斷路器 - WenqiENQ
- 使用Resilience4J實現斷路器模式模式
- 真機除錯裝置不夠?華為AGConnect雲除錯幫你忙除錯GC
- 女性想健康,AI來幫忙AI
- 自制分散式漏洞掃描分散式
- 帶有Resilience4j斷路器的Spring雲閘道器 - romeSpring
- Java 專案中使用 Resilience4j 框架實現隔斷機制/斷路器Java框架
- 特性標記清理:GitHub Actions 來幫忙!Github
- 故障模型哪家強?PDR 模型來幫忙模型
- spring cloud微服務分散式雲架構(四)-斷路器(Hystrix)SpringCloud微服務分散式架構
- 請各位大佬幫忙看看我的 Page Object 模式用的對不對Object模式
- 誤刪GreatSQL資料?別慌,Binlog來幫忙SQL
- rxjava回撥地獄-kotlin協程來幫忙RxJavaKotlin
- CRM能夠帶來哪些幫助?
- Android Studio用久了,磁碟越來越不夠用?如何破?Android
- 雙十一:女性脫單攻略 讓大資料來幫忙大資料
- 企業OA升級遇阻?小程式容器來幫忙
- 魔幻美國大選:網路技術不夠硬,黑客幫你選總統黑客
- 小企業抱怨谷歌援助是噱頭:幫不上忙還燒錢谷歌
- 分散式系統中的分散式鏈路追蹤與分散式呼叫鏈路分散式
- (十三)spring cloud微服務分散式雲架構-服務容錯保護(Hystrix斷路器)SpringCloud微服務分散式架構
- 5G安全建設怎麼搞?綠盟 MagicFlow 來幫忙
- GitLab 老舊版本升級難?極狐GitLab 專家來幫忙!Gitlab
- 0停機遷移Nacos?Java位元組碼技術來幫忙Java
- AutoML不夠用,智慧系統才是人工智慧的未來TOML人工智慧
- 智慧斷路器應用方案之智慧路燈杆應用方案
- 智慧斷路器應用方案之智慧消防用電
- 分散式服務防雪崩熔斷器,Hystrix理論+實戰。分散式
- 弱結構化日誌 Flink SQL 怎麼寫?SLS SPL 來幫忙SQL
- 免費|疫期遠端高效安全辦公,綠盟科技來幫忙
- 用斷路器馴服資料質量
- ZooKeeper分散式配置——看這篇就夠了分散式
- 斷路器HystrixCircuitBreakerUI
- 華納雲:伺服器C盤不夠用如何擴容伺服器
- 智慧斷路器與傳統斷路器的區別?
- 大夥幫忙給點人生建議哈!
- 請豆包幫忙總結翻譯一個網站,翻譯效果還不錯網站