搜尋文件

輸入關鍵字,搜尋標題與正文。

    訊息佇列與事件驅動架構文件 11/12

    積壓、觀測與故障驗證

    本文提要

    佇列變短,可能是工作完成,也可能是訊息正在處理、移入死信或已過期。 要判斷非同步流程是否履行承諾,必須把傳遞進度與業務結果一起觀察。

    18px · 寬鬆行距

    閱讀設定

    排版預覽 · 示範文字(可捲動)

    檔案與目錄

    Linux 以一棵從根目錄 / 開始的樹狀結構組織檔案。目錄用來整理檔案,也可以包含其他目錄。

    pwd
    ls -la /home
    18px

    16、18、20、22px;隨瀏覽器文字大小縮放。

    欄寬套用於背景文章;此處預覽字級與行距。手機正文自動配合螢幕。

    文件與本文目錄
    本主題文件

    佇列變短,可能是工作完成,也可能是訊息正在處理、移入死信或已過期。 要判斷非同步流程是否履行承諾,必須把傳遞進度與業務結果一起觀察。

    本文承接重播、投影與歷史資料。沿用匯出服務,先訂出可觀察的完成條件,再選指標與故障歷程;不把監控畫面上的綠燈當成正確性的證明。

    查證日期:2026-11-04。依當日 AWS 與 OpenTelemetry 官方文件及 Kafka 4.1 文件整理。數值、告警條件與下列故障歷程均為自創概念推演,未部署 broker、執行負載或故障注入。

    先為三種進度建立不同證據

    對 job-42,產品承諾是受理後可查詢成功結果或明確的終止原因。搜尋與通知則各有自己的下游契約。要診斷「使用者沒有看到匯出」,至少分開看三層:

    表格・3 欄 3 列
    層次本例紀錄能回答的問題
    受理與待發工作建立時間、Outbox 未發布筆數及最早等待時間工作是否保存?是否卡在交給 broker 之前?
    傳遞與消費可讀積壓、處理中、重試與死信、各訂閱進度哪一段還沒前進?是否只在反覆接收同一事件?
    業務完成工作終態、結果識別、各下游處理結果與未知狀態檔案是否可用?搜尋是否可查?通知是否仍需核對?

    如果 Outbox 卡住,broker 可能完全沒有積壓;如果 worker 收到後就過早刪除訊息,queue 也可能很乾淨。兩種情況都不能從「queue 為零」推出所有已受理工作成功。

    每層都需要自己的時間與識別。受理到成功的端到端延遲(end-to-end latency)由業務受理與終態紀錄量測;broker 內等待年齡只涵蓋其中一段。仍未完成的工作不能從成功延遲統計中無聲消失,應另外統計未終止數量、等待年齡與超過承諾期限的比例。

    訊息數、年齡與完成率要一起看

    積壓(backlog)表示尚待處理的工作;不同系統的指標可能只涵蓋「可見」或「尚未提交」的部分,使用前必須確認定義。

    SQS 的多項 CloudWatch 數值是近似值。ApproximateNumberOfMessagesVisible、ApproximateNumberOfMessagesNotVisible 分別提供可接收與處理中訊息的線索;單看前者下降,不能判斷後者是否卡住。接收與刪除次數也可能包含重複,不能直接當成唯一業務完成數。參考 SQS:Available CloudWatch metrics。

    同頁也說明 standard queue 的反覆失敗訊息會影響最老訊息年齡的呈現;因此年齡改善不必然表示壞訊息已修好。仍應獨立觀察死信,並保留應用的原始受理時間。不能以 DLQ 的指標年齡取代整項工作的等待時間。

    Kafka 的落後量(lag)要說明比較的是哪兩個位置。例如本例以「每個 partition 可讀尾端位置與該 group 已提交位置的差」作操作線索;它不是通用的秒數,也不自動代表業務未完成筆數。錯誤地提早提交會讓這個差看似健康,外部效果卻仍遺漏;同一段位置差,處理成本也可能不同。位置與效果的界線見 Kafka 4.1:Design,Consumer position、Message Delivery Semantics。

    官方監控名稱也不能直接套用上面的自訂定義。Kafka 4.1 的 records-lag-max 依目前讀取位置(current offset)而不是已提交位置計算;它可能在 worker pool 尚未完成效果時下降。選指標時先記下量測端點,再對照應用完成紀錄。參考 Kafka 4.1:Monitoring,consumer-fetch-manager-metrics。

    用明列假設估算能否排空

    假設系統已有 600 個待處理工作,新工作每秒增加 8 個,worker 每秒能完成 10 個。所有工作成本相同,沒有重試、額外流入或容量變動,淨排空速度是每秒 2 個,約需 600 ÷ (10 − 8) = 300 秒。

    若故障恢復後只是回到每秒完成 8 個,舊積壓就不會下降;若重試又增加流量,情況可能更差。這只是自訂算例,不是實測吞吐,也不能直接用平均值承諾每位使用者的最長等待。

    AWS 的積壓處理經驗強調背壓、工作優先順序與恢復策略;queue 可以延長恢復時間,不能只依平常吞吐規劃。參考 AWS:Avoiding insurmountable queue backlogs。擴大 consumer 之前仍要檢查資料庫、檔案儲存與外部通知能否承受,避免把積壓移到下一層。

    用識別串起歷程,不把追蹤當成去重

    本例的紀錄至少關聯意圖 export-intent-7、工作 job-42、命令 cmd-42、事件的 source + id、訂閱/consumer 名稱、處理嘗試及結果。每次投遞另有自己的追蹤資訊,不能讓新的 trace ID 取代既有事件身分。

    OpenTelemetry 的 context propagation 用來跨程序傳遞追蹤關聯,讓不同服務的活動可被串連。它不提供業務交易、去重或授權保證;缺少 span 也可能來自取樣、未插樁或資料遺失,不能直接推論工作沒有執行。參考 OpenTelemetry:Context propagation。

    以 job_id 查詢個案適合放在紀錄或追蹤中;長期指標標籤則應控制基數,按服務、訂閱與錯誤類別彙總。本文不要求把每個工作與事件 ID 都變成一組獨立時間序列。

    先寫判定規則,再設計故障歷程

    以下是待實作系統可採用的驗證規格,並非本次已執行的測試。每個案例都要記錄故障點、持久狀態、重送身分、恢復動作與最後的可觀察結果。

    表格・3 欄 5 列
    概念故障歷程觀察與應符合的條件可發現的錯誤
    broker 接受 evt-90,relay 尚未保存發布進度便停止恢復後可能重送同事件;適用本地交易的 consumer 效果不再累加每次重送改新事件 ID;Inbox 與效果分開提交
    worker A 暫停到可見性期限之後,B 接手,再讓 A 恢復本例受控結果更新應拒絕舊處理世代;檢查真正的結果紀錄只用 timeout 推論 A 已停止;舊 worker 覆蓋新結果
    某事件格式不受支援,重試後進入隔離保留原事件與錯誤;有負責人修復,正常訂閱可繼續無限立即重試;移入 DLQ 後直接視為業務成功
    搜尋 consumer 暫停,通知仍正常各自進度分開;搜尋恢復後在保存範圍內追上不同責任誤放同一競爭訂閱;共用進度
    新投影重建時仍有即時事件與資料刪除切換後沒有狀態倒退,也沒有復活已刪資料只檢查歷史批次完成,未涵蓋追趕與刪除

    「最後完成了」只能檢查進展,還要查不該發生的結果:同意圖出現兩個工作、已完成狀態倒退、跨租戶讀取或重寄歷史通知。外部服務若無法查明是否已執行,正確結果可能是保留 unknown 並進入核對,而非硬填成功或失敗。

    告警必須有處置對象

    可以分開設計「Outbox 等待過久」「某訂閱年齡上升」「死信出現」「工作超過終態期限」「外部效果未知未核對」等告警。門檻來自產品時間承諾與量測,本文不替所有系統設定固定秒數。

    每則告警應指出負責人、查詢入口、是否限制新流入、如何安全重試及何時停止。處置後應回查工作與副作用;把 queue 清空、刪掉死信或重設 offset,都不能自行證明需求已滿足。

    下一篇把上述證據與前文機制組成匯出完成後的多下游處理,逐步說明哪些保證成立、哪些仍需核對。

    相關文件