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
- 幫幫忙Veritas為什麼連不上oracleOracle
- 各位高手請幫忙,不勝感激!!!!
- 女性想健康,AI來幫忙AI
- 帶有Resilience4j斷路器的Spring雲閘道器 - romeSpring
- 關於分散式異構系統的問題!請幫忙看看分散式
- dx幫忙::跨異構平臺的分散式事務處理.分散式
- Java 專案中使用 Resilience4j 框架實現隔斷機制/斷路器Java框架
- 修汽車也可以用智慧裝置來幫忙了?
- 故障模型哪家強?PDR 模型來幫忙模型
- 有誰用過spring的tag的,進來幫個忙。Spring
- 高手幫忙
- 高手幫忙!
- 請各位大佬幫忙看看我的 Page Object 模式用的對不對Object模式
- spring cloud微服務分散式雲架構(四)-斷路器(Hystrix)SpringCloud微服務分散式架構
- 各位大哥,jboss配置資料來源的問題,幫幫忙!
- 請高手幫忙!
- 急,高手幫忙!
- 用jboss和mysql做過開發的朋友幫幫忙!!!MySql
- 採用斷路器設計模式來保護軟體設計模式
- serveroutput size不夠用Server
- 用URLClassLoader無法實現重新載入類,幫幫忙
- 救命啊!哪位大哥幫幫忙啊 程式出來很大的問題哦
- 熟悉ibatis的請幫幫忙!BAT
- 急!!請高手幫忙
- jbuilder高手請幫忙UI
- 請各位高手幫忙!
- 需要高手幫忙~~
- 魔幻美國大選:網路技術不夠硬,黑客幫你選總統黑客
- 雙十一:女性脫單攻略 讓大資料來幫忙大資料
- rxjava回撥地獄-kotlin協程來幫忙RxJavaKotlin
- 誤刪GreatSQL資料?別慌,Binlog來幫忙SQL