持久功能 - 空闲后重新启动的活动功能?
Posted
技术标签:
【中文标题】持久功能 - 空闲后重新启动的活动功能?【英文标题】:Durable Functions - Activity Function Restarted After Idle? 【发布时间】:2021-10-29 12:20:16 【问题描述】:由于 Azure 内置负载均衡器上的 non-configurable 230-second timeout,我们在应用服务中有一个长时间运行的进程(可能需要超过 5 分钟)。
所以我们使用 Azure Durable Functions 重构为 async-http API pattern。由于超出本问题范围的原因,我们有一个单一的活动功能,不能轻易分解成更小的工作。
我注意到输出日志中有奇怪的结果,并确定活动函数在几分钟后被 Azure Functions重新启动。我在活动函数中设置了一个断点,几分钟后它(再次)被命中。
这不是我自己配置的;我启动函数的调用代码只执行一次。这是怎么回事?如何使活动功能运行完成?
当工作量少于几分钟时,它可以正常工作并按预期完成。
函数应用代码如下所示:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using OurContentModel;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace Content20.Store
public class StoreContent
/// <summary>
/// Starter function called by HTTP. Starts the orchestrator and returns an endpoint the client
/// can query for status and for the result once complete.
/// </summary>
/// <remarks>See https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-overview?tabs=csharp#async-http </remarks>
[FunctionName("StoreContent")]
public async Task<IActionResult> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")]
HttpRequest req,
[DurableClient] IDurableOrchestrationClient starter,
ILogger log)
// Get function input comes from the request content and query params.
// ...
var content = JsonConvert.DeserializeObject<OurData>(requestBody);
string instanceId = await starter.StartNewAsync(
"StoreContent_RunOrchestrator",
new StoreContentInputArgs()
OurContent = content
);
log.LogInformation($"Started orchestration with ID = 'instanceId'.");
return starter.CreateCheckStatusResponse(req, instanceId);
/// <summary>
/// Orchestration function that calls the activity function(s)
/// and returns the final result when they're done.
/// </summary>
[FunctionName("StoreContent_RunOrchestrator")]
public async Task<StoreContentResult> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
var input = context.GetInput<StoreContentInputArgs>();
return await context.CallActivityAsync<StoreContentResult>("StoreContent_WriteFamilyData", input);
/// <summary>
/// Activity function that does the actual work.
/// </summary>
[FunctionName("StoreContent_WriteFamilyData")]
public async Task<StoreContentResult> WriteFamilyData([ActivityTrigger] StoreContentInputArgs input, ILogger log)
try
// breakpoint here gets hit a second time when first invocation takes more than a few minutes,
// with "external code" below it in the call stack so I assume it's getting (re)started by the system?
var storer = new OurContentStorer(log);
await storer.StoreContentAsync(input); // long-running process
return new StoreContentResult()
Success = true,
Message = "OK"
;
catch (Exception ex)
log.LogError(ex, ex.ToString());
return new StoreContentResult()
Success = false,
Message = ex.Message
;
我们已经在host.json
中将函数的超时时间增加到了一个小时。它在 Azure 的高级计划中运行。
当我在活动函数中设置中断时,调用堆栈在第二次命中断点时如下所示:
【问题讨论】:
【参考方案1】:事实证明,“重新启动”实际上只是剩余的调用。在某些时候,我已经终止了该进程(这都是使用 Azure Functions Tools 进行的所有本地调试),并且它在我的 Azure 存储模拟器中留下了一些状态。所以我的本地 Azure 工具认为持久功能仍在运行和/或需要重新启动。
为了摆脱僵尸调用,我刚刚使用 Azure Storage Explorer 从我的模拟器中删除了所有“testhub”表、队列和 blob。当您在本地运行持久函数时,这些会自动生成。
【讨论】:
以上是关于持久功能 - 空闲后重新启动的活动功能?的主要内容,如果未能解决你的问题,请参考以下文章