持久功能 - 空闲后重新启动的活动功能?

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。当您在本地运行持久函数时,这些会自动生成。

【讨论】:

以上是关于持久功能 - 空闲后重新启动的活动功能?的主要内容,如果未能解决你的问题,请参考以下文章

使用jQuery单击操作后重新启动功能

按HOME后重新启动应用程序时如何返回最新启动的活动?

禁用启动器活动后,android重新安装失败

当应用程序关闭并重新启动时,如何继续上一个活动?

如何以编程方式“重新启动”android应用程序[重复]

从另一个活动重新创建/重新启动活动