Azure Functions 錯誤處理和重試
處理 Azure Functions 中的錯誤十分重要,可協助您避免遺失資料、避免遺漏事件以及監視應用程式的健康情況。 這也是協助您了解事件型觸發程序的重試行為的重要方式。
本文說明錯誤處理和可用重試策略的一般策略。
重要
2022 年 12 月已移除特定觸發程式的預覽重試原則支援。 支持的觸發程式的重試原則現已正式推出(GA)。 如需目前支援重試原則的延伸模塊清單,請參閱 重試 一節。
處理錯誤
Azure 函式中發生的錯誤可能來自:
- 使用內建的 Functions 觸發程式和系結。
- 呼叫基礎 Azure 服務的 API。
- 呼叫 REST 端點。
- 呼叫客戶端連結庫、套件或第三方 API。
若要避免遺失資料或遺漏訊息,良好的錯誤處理做法十分重要。 下表描述一些建議的錯誤處理做法,並提供詳細信息的連結。
建議 | 詳細資料 |
---|---|
啟用 Application Insights | Azure Functions 與 Application Insights 整合,以收集錯誤資料、效能資料和執行階段記錄。 您應該使用 Application Insights 來探索並進一步了解函式執行中發生的錯誤。 若要深入了解,請參閱監視 Azure Functions。 |
使用結構化錯誤處理 | 擷取及記錄錯誤對於監視應用程式的健康狀態至關重要。 任何函式程式碼的最上層都應該包含 try/catch 區塊。 在 catch 區塊中,您可以擷取及記錄錯誤。 如需繫結可能引發哪些錯誤的相關資訊,請參閱繫結錯誤碼。 視您的特定重試策略而定,您可能也會引發新的例外狀況,再次執行函式。 |
規劃重試策略 | 數個 Functions 系結延伸模組提供重試的內建支援,而其他函式則可讓您定義 Functions 運行時間所實作的重試原則。 對於未提供重試行為的觸發程式,您應該考慮實作自己的重試配置。 如需詳細資訊,請參閱 重試。 |
設計等冪性 | 處理資料時發生錯誤可能是函式的問題,特別是在處理訊息時。 務必考慮發生錯誤時會發生什麼情況,以及如何避免重複處理。 若要深入了解,請參閱設計相同輸入的 Azure Functions。 |
重試
函式有兩種可用的重試:
- 個別觸發程序延伸模組的內建重試行為
- Functions 執行階段提供的重試原則
下表指出哪些觸發程序支援重試,以及設定重試行為的位置。 它也會連結至來自基礎服務的錯誤詳細資訊。
觸發程序/繫結 | 重試來源 | 組態 |
---|---|---|
Azure Cosmos DB | 重試原則 | 函數層級 |
Blob 儲存體 | 繫結延伸模組 | host.json |
事件方格 | 繫結延伸模組 | 事件訂閱 |
事件中樞 | 重試原則 | 函數層級 |
Kafka | 重試原則 | 函數層級 |
佇列儲存體 | 繫結延伸模組 | host.json |
RabbitMQ | 繫結延伸模組 | 無效信件佇列 |
服務匯流排 | 繫結延伸模組 | host.json* |
計時器 | 重試原則 | 函數層級 |
*需要 5.x 版的 Azure 服務匯流排 擴充功能。 在舊版擴充功能中,重試行為是由寄不出的信件佇列 服務匯流排 實作。
重試原則
Azure Functions 可讓您為運行時間強制執行的特定觸發程式類型定義重試原則。 這些觸發程式類型目前支援重試原則:
v1 和 v2 Python 程式設計模型的重試支援都相同。
Functions 運行時間 1.x 版不支援重試原則。
除非成功完成或達到重試次數上限,否則重試原則會告知執行階段重新執行失敗的執行。
當支援的觸發程式類型執行的函式引發未攔截的例外狀況時,就會評估重試原則。 最佳做法是,您應該攔截程序代碼中的所有例外狀況,並針對您想要重試的任何錯誤引發新的例外狀況。
重要
在執行重試原則完成之前,不會寫入事件中樞檢查點。 由於此行為,特定分割區的進度會暫停,直到目前批次完成處理為止。
事件中樞擴充功能 5.x 版支援 Functions 主機與事件中樞之間互動的其他重試功能。 如需詳細資訊,請參閱 clientRetryOptions
事件中 樞host.json參考。
重試策略
您可以設定原則支援的兩個重試策略:
在取用方案中執行時,您只需支付函式程式代碼執行的時間。 在上述任一重試策略中,執行之間的等候時間不會向您收取費用。
重試計數上限
您可以設定在最終失敗前重試函式執行的次數上限。 目前的重試計數會儲存於執行個體的記憶體中。
執行個體在重試嘗試之間可能會失敗。 當執行個體在重試原則期間失敗時,重試計數就會遺失。 發生執行個體失敗時,事件中樞觸發程序能夠繼續處理,並在新的執行個體上重試批次,並將重試計數重設為零。 計時器觸發程序不會在新執行個體上繼續。
此行為表示重試計數上限是最佳數量。 在某些情況下,執行可能會重試超過要求次數的上限。 針對計時器觸發程序,重試可以小於要求的次數上限。
重試範例
提供固定延遲和指數輪詢策略的範例。 若要查看特定策略的範例,您必須先在上一個索引標籤中選取該策略。
下列 NuGet 套件支援函式層級重試:
- Microsoft.Azure.Functions.Worker.Sdk>= 1.9.0
- Microsoft.Azure.Functions.Worker.Extensions.EventHubs>= 5.2.0
- Microsoft.Azure.Functions.Worker.Extensions.Kafka>= 3.8.0
- Microsoft.Azure.Functions.Worker.Extensions.Timer>= 4.2.0
[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"
}
}
您可以在重試原則定義上設定這些屬性:
屬性 | 說明 |
---|---|
策略 | 必要。 要使用的重試策略。 有效值為 fixedDelay 或 exponentialBackoff 。 |
maxRetryCount | 必要。 每個函式執行允許的重試次數上限。 -1 表示無限期重試。 |
delayInterval | 當您使用 fixedDelay 策略時,重試之間所使用的延遲。 將其指定為格式 HH:mm:ss 的字串。 |
minimumInterval | 使用 exponentialBackoff 策略時的重試延遲下限。 將其指定為格式 HH:mm:ss 的字串。 |
maximumInterval | 使用 exponentialBackoff 策略時的重試延遲上限。 將其指定為格式 HH:mm:ss 的字串。 |
您為觸發程式定義重試原則的方式取決於您的Node.js版本。
以下是使用固定延遲重試策略的定時器觸發程式函式範例:
const { app } = require('@azure/functions');
app.timer('timerTriggerWithRetry', {
schedule: '0 */5 * * * *',
retry: {
strategy: 'fixedDelay',
delayInterval: {
seconds: 10,
},
maxRetryCount: 4,
},
handler: (myTimer, context) => {
if (context.retryContext?.retryCount < 2) {
throw new Error('Retry!');
} else {
context.log('Timer function processed request.');
}
},
});
您為觸發程式定義重試原則的方式取決於您的Node.js版本。
以下是使用固定延遲重試策略的定時器觸發程式函式範例:
import { app, InvocationContext, Timer } from '@azure/functions';
export async function timerTriggerWithRetry(myTimer: Timer, context: InvocationContext): Promise<void> {
if (context.retryContext?.retryCount < 2) {
throw new Error('Retry!');
} else {
context.log('Timer function processed request.');
}
}
app.timer('timerTriggerWithRetry', {
schedule: '0 */5 * * * *',
retry: {
strategy: 'fixedDelay',
delayInterval: {
seconds: 10,
},
maxRetryCount: 4,
},
handler: timerTriggerWithRetry,
});
您可以在重試原則定義上設定這些屬性:
屬性 | 說明 |
---|---|
策略 | 必要。 要使用的重試策略。 有效值為 fixedDelay 或 exponentialBackoff 。 |
maxRetryCount | 必要。 每個函式執行允許的重試次數上限。 -1 表示無限期重試。 |
delayInterval | 當您使用 fixedDelay 策略時,重試之間所使用的延遲。 將其指定為格式 HH:mm:ss 的字串。 |
minimumInterval | 使用 exponentialBackoff 策略時的重試延遲下限。 將其指定為格式 HH:mm:ss 的字串。 |
maximumInterval | 使用 exponentialBackoff 策略時的重試延遲上限。 將其指定為格式 HH:mm:ss 的字串。 |
以下是使用固定延遲重試策略的定時器觸發程式函式範例:
import logging
from azure.functions import AuthLevel, Context, FunctionApp, TimerRequest
app = FunctionApp(http_auth_level=AuthLevel.ANONYMOUS)
@app.timer_trigger(schedule="*/1 * * * * *", arg_name="mytimer",
run_on_startup=False,
use_monitor=False)
@app.retry(strategy="fixed_delay", max_retry_count="3",
delay_interval="00:00:01")
def mytimer(mytimer: TimerRequest, context: 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.info(
f"Max retries of {context.retry_context.max_retry_count} for "
f"function {context.function_name} has been reached")
else:
raise Exception("This is a retryable exception")
您可以在重試原則定義上設定這些屬性:
屬性 | 說明 |
---|---|
策略 | 必要。 要使用的重試策略。 有效值為 fixed_delay 或 exponential_backoff 。 |
max_retry_count | 必要。 每個函式執行允許的重試次數上限。 -1 表示無限期重試。 |
delay_interval | 當您使用 fixed_delay 策略時,重試之間所使用的延遲。 將其指定為格式 HH:mm:ss 的字串。 |
minimum_interval | 使用 exponential_backoff 策略時的重試延遲下限。 將其指定為格式 HH:mm:ss 的字串。 |
maximum_interval | 使用 exponential_backoff 策略時的重試延遲上限。 將其指定為格式 HH:mm:ss 的字串。 |
@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。 下列文章的<例外狀況和傳回碼>一節提供繫結特定錯誤的相關資訊: