問題描述
Azure Function HTTP 觸發后, 230秒就超時,而其他方式觸發的Function, 執行5分鍾后也超時,如何調整超時時間?
HTTP觸發的Function 報錯500 - The Request timed out 消息截圖:
問題分析
查閱官方文檔,對函數應用超時持續時間有詳細介紹:最新的3.X版本的默認值根據Function計划的類型不同而不同,默認的最少為5分鍾,最大30分鍾。消耗計划的Function最大可調整為10分鍾,而其他兩種無限制。
但是,非常非常重要的一點是:如果Function是HTTP觸發類型。它的響應時間最大最大就是230秒。 這是因為 Azure 負載均衡器的默認空閑超時就是230秒,作為PaaS服務的Azure Funciton (相同的還有App Service)無法改動。
(Source : https://docs.microsoft.com/zh-cn/azure/azure-functions/functions-scale#function-app-timeout-duration)
問題解決
1) 進入Function App的Azure 門戶頁面: Function App - Microsoft Azure 由世紀互聯運營
2) 點擊“App Service Editor “, 進入源代碼查看頁面,選擇 host.json。 修改 functionTimeout 內容。如沒有 functionTimeout,則根據以下格式自行添加。
3)如果是 HTTP觸發的函數,而且其Function所運行的任務會處理很長時間,建議使用Function的另一種模式 【Durable Function 異步模式】, 或者通過代碼的方式,自行解決延遲響應返回。
Durable Function 異步模式
異步 HTTP API 模式解決了使用外部客戶端協調長時間運行的操作的狀態時出現的問題。 實現此模式的一種常用方式是讓 HTTP 終結點觸發長時間運行的操作。 然后,將客戶端重定向到某個狀態終結點(Location),客戶端可輪詢該終結點(Location),以了解操作是何時完成的。
Durable Functions 默認支持HTTP API 異步模式,可以簡化甚至消除為了與長時間運行的函數執行進行交互而需要編寫的代碼。
- C#代碼可以參考:使用 C# 創建你的第一個持久函數(https://docs.microsoft.com/zh-cn/azure/azure-functions/durable/durable-functions-create-first-csharp?pivots=code-editor-vscode)
- JavaScript代碼參考:使用 JavaScript 創建你的第一個持久函數(https://docs.microsoft.com/zh-cn/azure/azure-functions/durable/quickstart-js-vscode)
啟動實例后,該擴展會公開 Webhook HTTP API 用於查詢業務流程協調程序函數的狀態。
Durable Function 異步模式Demo:
根據入門文檔創建的簡易代碼中,主要有三個部分:
1)第一個函數 HttpStart, Demo中調用名為 DurableFunctionsOrchestrationCSharp1_HttpStart, 它是Durable Function函數的觸發入口,他會啟動真正的業務代碼,並且返回一個響應URL,用於輪詢執行結果。
2)第二個函數 RunOrchestrator,Demo中的調用名為 DurableFunctionsOrchestrationCSharp1, 它是一個把需要執行的任務集中在一起,形成一個執行列表,當列表中的函數執行完成后,返回結果。
3)第三個函數 SayHello, Demo中的調用名為 DurableFunctionsOrchestrationCSharp1_Hello, 它里面是需要真正執行的業務邏輯。
PS: 為了能讓函數執行時間更長,所以在第二步中,為每個函數之間添加了100秒的延遲,這樣總的執行時間就會達到300秒。超過230秒的HTTP平台限制。
public static class DurableFunctionsOrchestrationCSharp1 { [FunctionName("DurableFunctionsOrchestrationCSharp1")] public static async Task<List<string>> RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { var outputs = new List<string>(); // Replace "hello" with the name of your Durable Activity Function. outputs.Add(await context.CallActivityAsync<string>("DurableFunctionsOrchestrationCSharp1_Hello", "Tokyo")); Task.Delay(100000).Wait(); outputs.Add(await context.CallActivityAsync<string>("DurableFunctionsOrchestrationCSharp1_Hello", "Seattle")); Task.Delay(100000).Wait(); outputs.Add(await context.CallActivityAsync<string>("DurableFunctionsOrchestrationCSharp1_Hello", "London")); Task.Delay(100000).Wait(); // returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"] return outputs; } [FunctionName("DurableFunctionsOrchestrationCSharp1_Hello")] public static string SayHello([ActivityTrigger] string name, ILogger log) { log.LogInformation($"Saying hello to {name}."); return $"Hello {name}!"; } [FunctionName("DurableFunctionsOrchestrationCSharp1_HttpStart")] public static async Task<HttpResponseMessage> HttpStart( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req, [DurableClient] IDurableOrchestrationClient starter, ILogger log) { // Function input comes from the request content. string instanceId = await starter.StartNewAsync("DurableFunctionsOrchestrationCSharp1", null); log.LogInformation($"Started orchestration with ID = '{instanceId}'."); return starter.CreateCheckStatusResponse(req, instanceId); } }
注意:.Net Core 中使用 Task.Delay(100000).Wait(); 方法來實現線程睡眠。與傳統的Thread.Sleep(1000)有一些區別。
使用VS Code創建和發布 Durable Function 異步模式Demo 到Azure演示
測試 Durable Function HTTP異步演示(使用瀏覽器)
參考資料
函數應用超時持續時間: https://docs.microsoft.com/zh-cn/azure/azure-functions/functions-scale#function-app-timeout-duration
Function host.json functionTimeout : https://docs.microsoft.com/zh-cn/azure/azure-functions/functions-host-json#functiontimeout
Durable Function 異步 HTTP API 模式: https://docs.microsoft.com/zh-cn/azure/azure-functions/durable/durable-functions-overview?tabs=csharp#pattern-3-async-http-apis
【完】