Azure Functions 錯誤處理和重試

處理 Azure Functions 中的錯誤非常重要,可協助您避免遺失數據、避免遺漏事件,以及監視應用程式的健康情況。 這也是協助您瞭解事件型觸發程式的重試行為的重要方式。

本文說明錯誤處理的一般策略和可用的重試策略。

重要

在此功能正式推出之後,我們會移除運行時間中定時器、Kafka 和事件中樞以外的觸發程式的重試原則支援。 2022 年 12 月已移除定時器和事件中樞以外的所有觸發程式的預覽重試原則支援。 如需詳細資訊,請參閱 重試 一節。

處理錯誤

Azure 函式中發生的錯誤可能是下列任何一項所造成:

  • 使用內建的 Azure Functions 觸發程式和系結
  • 呼叫基礎 Azure 服務的 API
  • 對 REST 端點的呼叫
  • 對客戶端連結庫、套件或第三方 API 的呼叫

若要避免遺失數據或遺失訊息,請務必練習良好的錯誤處理。 本節說明一些建議的錯誤處理做法,並提供詳細信息的連結。

啟用 Application Insights

Azure Functions 會與 Application Insights 整合,以收集錯誤數據、效能數據和運行時間記錄。 您應該使用 Application Insights 來探索並進一步瞭解函式執行中發生的錯誤。 若要深入瞭解,請參閱 監視 Azure Functions

使用結構化錯誤處理

擷取和記錄錯誤對於監視應用程式的健康情況非常重要。 任何函式程式代碼的最上層都應該包含 try/catch 區塊。 在 catch 區塊中,您可以擷取和記錄錯誤。 如需系結可能會引發哪些錯誤的資訊,請參閱 系結錯誤碼

規劃重試策略

數個 Functions 系結延伸模組提供重試的內建支援。 此外,運行時間可讓您定義定時器、Kafka 和事件中樞觸發函式的重試原則。 若要深入瞭解,請參閱 重試。 針對未提供重試行為的觸發程式,您可能想要實作自己的重試配置。

設計等冪性

當您處理數據時發生錯誤可能是函式的問題,特別是當您處理訊息時。 請務必考慮錯誤發生時會發生什麼情況,以及如何避免重複處理。 若要深入瞭解,請參閱 為相同的輸入設計 Azure Functions。

重試

函式有兩種可用的重試:

  • 個別觸發程式延伸模組的內建重試行為
  • Functions 運行時間提供的重試原則

下表指出哪些觸發程式支援重試,以及設定重試行為的位置。 它也連結至來自基礎服務之錯誤的詳細資訊。

觸發程式/系結 重試來源 組態
Azure Cosmos DB 重試原則 函式層級
Azure Blob 儲存體 系結延伸模組 host.json
事件格線 系結延伸模組 事件訂閱
Azure 事件中樞 重試原則 函式層級
Azure 佇列儲存體 系結延伸模組 host.json
RabbitMQ 系結延伸模組 寄不出的信件佇列
Azure 服務匯流排 系結延伸模組 寄不出的信件佇列
計時器 重試原則 函式層級
Kafka 重試原則 函式層級

重試原則

從 Azure Functions 運行時間 3.x 版開始,您可以為 Functions 運行時間強制執行的定時器、Kafka、事件中樞和 Azure Cosmos DB 觸發程式定義重試原則。

重試原則會告知運行時間重新執行失敗的執行,直到成功完成或達到重試次數上限為止。

當定時器、Kafka、事件中樞或 Azure Cosmos DB 觸發的函式引發未攔截的例外狀況時,就會評估重試原則。 最佳做法是,您應該攔截程序代碼中的所有例外狀況,並重新擲回您想要重試的任何錯誤。

重要

在執行重試原則完成之前,不會寫入事件中樞檢查點。 由於此行為,特定分割區的進度會暫停,直到目前批次完成為止。

事件中樞 v5 擴充功能支援其他重試功能,以進行 Functions 主機與事件中樞之間的互動。 如需詳細資訊,請參閱clientRetryOptionshost.json檔案的 <事件中樞>一節。

重試策略

您可以設定原則支援的兩個重試策略:

允許在每次重試之間經過指定的時間量。

重試計數上限

您可以設定在最終失敗之前重試函式執行的最大次數。 目前的重試計數會儲存在 實例的記憶體中。

實例在重試嘗試之間可能會失敗。 當實例在重試原則期間失敗時,重試計數就會遺失。 發生實例失敗時,事件中樞觸發程式能夠繼續處理,並在新的實例上重試批次,並將重試計數重設為零。 定時器觸發程式不會在新實例上繼續。

此行為表示重試計數上限是最佳努力。 在某些情況下,可能會重試執行次數超過要求的最大次數。 針對定時器觸發程式,重試次數可能小於所要求的最大數目。

重試範例

下列 NuGet 套件支援函式層級重試:

[Function(nameof(TimerFunction))]
[FixedDelayRetry(5, "00:00:10")]
public static void Run([TimerTrigger("0 */5 * * * *")] TimerInfo timerInfo,
    FunctionContext context)
{
    var logger = context.GetLogger(nameof(TimerFunction));
    logger.LogInformation($"Function Ran. Next timer schedule = {timerInfo.ScheduleStatus.Next}");
}
屬性 說明
MaxRetryCount 必要。 每個函式執行允許的重試次數上限。 -1 表示無限期重試。
DelayInterval 重試之間所使用的延遲。 將它指定為格式 HH:mm:ss為 的字串。

以下是function.json檔案中的重試原則:

{
    "disabled": false,
    "bindings": [
        {
            ....
        }
    ],
    "retry": {
        "strategy": "fixedDelay",
        "maxRetryCount": 4,
        "delayInterval": "00:00:10"
    }
}
function.json 屬性 描述
策略 必要。 要使用的重試策略。 有效值為 fixedDelayexponentialBackoff
maxRetryCount 必要。 每個函式執行允許的重試次數上限。 -1 表示無限期重試。
delayInterval 當您使用 fixedDelay 策略時,重試之間所使用的延遲。 將它指定為格式 HH:mm:ss為 的字串。
minimumInterval 當您使用 exponentialBackoff 策略時,重試延遲下限。 將它指定為格式 HH:mm:ss為 的字串。
maximumInterval 當您使用 exponentialBackoff 策略時,重試延遲上限。 將它指定為格式 HH:mm:ss為 的字串。

以下是使用函式中重試內容的 Python 範例:

import azure.functions
import logging


def main(mytimer: azure.functions.TimerRequest, context: azure.functions.Context) -> None:
    logging.info(f'Current retry count: {context.retry_context.retry_count}')

    if context.retry_context.retry_count == context.retry_context.max_retry_count:
        logging.warn(
            f"Max retries of {context.retry_context.max_retry_count} for "
            f"function {context.function_name} has been reached")

@FunctionName("TimerTriggerJava1")
@FixedDelayRetry(maxRetryCount = 4, delayInterval = "00:00:10")
public void run(
    @TimerTrigger(name = "timerInfo", schedule = "0 */5 * * * *") String timerInfo,
    final ExecutionContext context
) {
    context.getLogger().info("Java Timer trigger function executed at: " + LocalDateTime.now());
}

系結錯誤碼

當您與 Azure 服務整合時,錯誤可能源自基礎服務的 API。 下列文章的小節提供與系結特定錯誤相關的資訊:

下一步