在 Azure Functions 和 Event Hubs 中實現可靠的事件處理

學習如何利用 Azure Functions 搭配 Azure 事件中樞 觸發器,建立穩健且可靠的無伺服器解決方案。 本文將介紹檢查點、錯誤處理及熔斷機制模式的最佳實務,確保不遺失任何事件,並讓事件驅動的應用程式保持穩定與韌性。

分散式系統中事件數據流的挑戰

請考慮以每秒 100 個事件的固定速率傳送事件的系統。 以此速率,多個平行執行個體可以處理每秒傳入的 100 個事件。

不過,請考慮在取用事件流時面臨的這些挑戰:

  • 事件發行者會傳送損壞事件。
  • 您的函式程式代碼遇到未處理的例外狀況。
  • 下游系統離線並封鎖事件處理。

Azure 事件中樞與會在處理期間鎖定訊息的 Azure Queue 儲存體觸發程序不同,它會針對每個分割區,從串流中的單一點讀取。 此讀取行為類似於視頻播放器,提供了高吞吐量、多個消費者群組和重播能力所需的優勢。 從檢查點向前或向後讀取事件,但您必須移動指標才能處理新事件。 更多資訊請參閱活動中心文件中的 檢查點 。

當數據流中發生錯誤,而您選擇不前進指標時,會封鎖進一步的事件處理。 換句話說,如果你停止指標處理單一事件的問題,未處理的事件就會開始堆積。

不論成功或失敗為何,函數都會移動資料流的指標,以避免死結。 因為指標會持續前進,因此您的函式必須適當地處理失敗。

事件中樞觸發程序如何取用事件

Azure Functions 按循環程序執行以下步驟,從事件中樞接收事件:

  1. 觸發器會在 Azure 儲存體 中為事件中心的每個分割區建立並持久化一個指標。
  2. 觸發器預設會以批次接收新事件,主機嘗試觸發該函式,提供該批次事件供處理。
  3. 當函式完成執行時,不論有無例外,觸發器會推進指標並儲存檢查點到預設的主機儲存帳號。
  4. 如果條件阻止函式執行完成,主機就無法推進指標。 當指標無法前進時,後續執行會重新處理相同的事件。

此行為會顯示一些重要點:

  • 未處理的例外狀況可能會導致您遺失事件:

    引發例外狀況的函式執行會使指標繼續前進。 設定 重試策略 或其他重試邏輯會延遲指標推進,直到整個重試完成。

  • 函式保證至少一次交付:

    您的程式代碼和相依系統可能需要考慮相同事件可以處理兩次的事實。 欲了解更多資訊,請參閱 為相同的輸入設計的 Azure Functions。

  • 檢查點狀態儲存在 Azure 儲存體:

    觸發程序會將檢查點 (處理指標) 保存到函式應用程式的 AzureWebJobsStorage 設定所設定的儲存體帳戶中。 此已儲存的檢查點參照表示:

    • 當你改 AzureWebJobsStorage 為參考不同的儲存帳戶時,函式會從新位置開始處理,這可能導致事件被重新處理。
    • 當事件集線器被刪除並重新建立時,事件串流位置(如序號和偏移量)會被重置,而儲存的檢查點參考則保持不變。 在這種情況下,函式可能不會處理新事件,直到檢查點被手動刪除。

處理例外狀況

雖然所有函式程式碼在最高層級都應該包含 嘗試/捕捉區塊 ,但對於消耗事件中心事件的函式來說,擁有 catch 區塊更為重要。 如此一來,當例外狀況被引發時,捕捉區塊會在指標移動之前處理錯誤。

重試機制和原則

因為雲端中的許多例外狀況都是暫時性的,因此錯誤處理的第一個步驟一律會重試作業。 您可以套用內建的重試原則,或定義您自己的重試邏輯。

重試原則

Azure Functions 會提供事件中樞的內建重試原則。 使用重試策略時,只要提出新的例外,主機就會根據定義的政策重新處理事件。 此重試行為需要事件中樞擴充功能 5.x 版或更新版本。 如需詳細資訊,請參閱重試原則。

自定義重試邏輯

您也可以在函式本身中定義自己的重試邏輯。 例如,您可以實作遵循下列規則所說明工作流程的原則:

  • 嘗試處理事件三次(可能在重試之間會有延遲)。
  • 如果所有重試的最終結果是失敗,請將事件新增至佇列,讓處理可以在數據流上繼續。
  • 稍後會再行處理那些已損毀或未經處理的事件。

備註

Polly 是一個用於 C# 應用程式的韌性與瞬態錯誤處理函式庫範例。

非異常錯誤

有時候問題可能會發生,卻不會引發例外狀況。 例如,假設要求逾時或執行函式的實例當機。 當函式因未拋出例外而無法完成時,位移指標將不會進階。 如果指標未前進,則在執行失敗後執行的任何實例都會繼續讀取相同的事件。 這種情況提供至少一次保證。

保證處理每個事件至少一次表示某些事件可以多次處理。 你的功能應用程式需要意識到這種可能性,並且必須圍繞 冪等性原則來構建。

處理失敗狀態

您的應用程式可能能夠成功地處理事件處理中的少許錯誤。 不過,您也應該準備好處理持續性失敗狀態,這可能會因為下游處理失敗而發生。 在這類失敗狀態中,例如下游數據存放區離線,您的函式應該停止對事件進行觸發,直到系統恢復正常運行為止。

斷路器模式

當你實作 斷路器 模式時,應用程式可以有效地暫停事件處理,並在問題解決後再繼續處理。

在事件串流進程中實作斷路器需要兩個元件:

  • 在所有實例上共享狀態,以追蹤和監視線路的健康情況。
  • 能夠管理線路狀態的主要過程,作為open或closed。

實作的詳細內容可能會有所不同,但要在實體之間共享狀態,則必須具備一個儲存機制。 你可以把狀態儲存在 Azure 儲存體、Redis 快取,或任何由你的函式應用程式實例存取的持久服務中。

Durable Functions 與 Azure Logic Apps 皆提供管理工作流程與電路狀態的基礎設施。 本文說明如何使用 Logic Apps 暫停和重新啟動函式執行,提供您所需的控制權來實作斷路器設計模式。

定義跨實例的失敗臨界值

當多個實例同時處理事件時,需要持續共享的外部狀態來監測系統狀況。 然後,您可以根據指出失敗狀態的規則來監視此持續性狀態,例如:

在所有實例的 30 秒內發生超過 100 個事件失敗時,請斷路以停止觸發新事件。

此監視邏輯的實作詳細數據會根據您的特定應用程式需求而有所不同,但一般而言,您必須建立一個系統:

  1. 將失敗記錄到持久化儲存。
  2. 檢查記錄新失敗時的滾動計數,以判斷是否符合事件失敗閾值。
  3. 符合此臨界值時,發出事件,告知系統中斷線路。

使用 Azure Logic Apps 管理線路狀態

Azure Logic Apps 包含可連接到不同服務、功能及具狀態協調流程的內建連接器。 管理電路狀態是很自然的選擇。 偵測線路何時必須中斷之後,您可以建置邏輯應用程式來實作此工作流程:

  1. 觸發事件方格工作流程,以停止函式處理。
  2. 傳送通知電子郵件,其中包含重新啟動工作流程的選項。

若想了解如何使用應用程式設定停用或重新啟用特定功能,請參閱「如何在 Azure Functions 中停用功能」。

電子郵件收件人可以調查電路的健康狀況,並在適當時透過通知郵件中的連結重新啟動電路。 當工作流程重新啟動函式時,會處理來自最後事件中心檢查點的事件。

使用這種方法時,你不會失去任何事件,會依序處理事件,並且可以隨時斷開迴路。

事件方格觸發程式的移轉策略

當您在區域之間或某些方案之間移轉現有的函數應用程式時,必須在移轉過程中重新建立應用程式。 在這種情況下,遷移過程中,你可能會有兩個應用程式,它們都能從同一個事件串流讀取並寫入相同的輸出目的地。

為避免遷移過程中事件資料遺失或重複,建議 使用消費者群組:

  1. 為新的目標應用程式建立新的取用者群組。

  2. 在新的應用程式中設定觸發器,以使用這個新的使用者群組。

    透過此方法,兩個應用程式能在驗證期間獨立處理事件。

  3. 驗證新應用程式正在正確處理事件。

  4. 關閉原始應用程式或移除其訂閱或用戶群組。