【问题标题】:Return immediately in HttpTrigger on Azure Function在 Azure Function 上的 HttpTrigger 中立即返回
【发布时间】:2020-04-02 15:09:02
【问题描述】:

我有一个带有 HttpTrigger 的 Azure 函数。

我想立即返回 202 Accepted 给调用者,然后实际处理调用,大约需要一秒钟。

是否有一些最佳实践方法可以做到这一点?

我不想在回电话之前做任何事情,所以首先调用 EventGrid 或类似的方法是不可能的。

被拒绝的选项

调用 EventGrid

通过调用 EventGrid,我可以在 EventGrid 调用完成后立即返回,实际处理可以在另一个订阅事件的函数中进行。我不希望这样做,因为调用 EventGrid 需要时间,并且它确实会不时失败或花费比正常时间更长的时间。

加入队列

通过将消息添加到队列中,我可以完成与使用 EventGrid 相同的操作,并且它也存在与上述相同的问题。

调用不带'await'的函数

我知道通过在我的函数内部调用一个方法而不等待,它不会等待响应,我将能够立即返回。但是,我的测试表明这是非常不现实的,但如果您认为这是可行的方法以及原因,请告诉我。

自定义线程

我可以使用 Thread 和 ThreadStart 等手动进行此操作,我想如果需要,我可能会这样做,但我问这个问题是为了寻找更好的解决方案。

【问题讨论】:

  • 您的 HttpTrigger 多久被调用一次?
  • 我已经使用 ThreadPool.QueueUserWorkerItemCloudEvents v1.0 处理了 AEG 端点验证的相同情况/b>。请注意,此解决方案适用于运行时间很短的后台任务。
  • @RomanKiss 抱歉回复晚了。假设它每秒被调用 5 次。

标签: azure-functions


【解决方案1】:

Durable Functions extension 可以提供帮助。

您可以通过 HTTP 启动一个编排,该编排将返回一个状态 URL,客户端可以轮询状态。

【讨论】:

  • 持久化函数实际上不是添加到表存储或后台队列来完成此任务吗?
  • 我想它会带来与添加到队列相同的非常轻微的性能损失。我的意思是,对于我所描述的场景来说,这是一个非常好的和强大的解决方案,但基本上我猜你可以说它等同于问题中描述的 EventGrid 和 Queue 选项?
  • 我认为它确实相当于同一件事,尽管您可能不必编写代码来执行此操作。
【解决方案2】:

有一个FunctionInvocationFilterAttribute 可能是您正在寻找的。此属性仍处于预览状态,但工作正常。您可以创建自己的属性来实现它,并通过覆盖OnExecutingAsync 方法来定义函数执行时要执行的操作。

类似的东西:

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Microsoft.Azure.WebJobs.Host;
using System.Threading;
using System.Linq;

namespace FunctionApp
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class ReturnResponseBeforeExecutionAttribute : FunctionInvocationFilterAttribute
    {
        public override Task OnExecutingAsync(FunctionExecutingContext executingContext, CancellationToken cancellationToken)
        {
            var request = executingContext.Arguments.Values.FirstOrDefault(argument => argument is HttpRequest) as HttpRequest;

            request.HttpContext.Response.StatusCode = 202;
            request.HttpContext.Response.Body.Flush();
            request.HttpContext.Response.Body.Close();
            return Task.CompletedTask;
        }
    }

    public class DoStuff
    {
        [ReturnResponseBeforeExecution]
        [FunctionName("DoStuff")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            string responseMessage = string.IsNullOrEmpty(name)
                ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
                : $"Hello, {name}. This HTTP triggered function executed successfully.";

            return new OkObjectResult(responseMessage);
        }
    }
}

编辑:刚刚意识到在返回响应之前它仍然等待函数执行。

【讨论】:

  • 不过,这看起来是一个了不起的解决方案,可惜没有奏效。
  • 您可以使用return Task.FromException(new UnauthorizedAccessException()); 而不是return Task.CompletedTask;。这将中止函数执行。实际上,您可以使用任何 Exception 类型返回它。
猜你喜欢
  • 1970-01-01
  • 2020-02-25
  • 1970-01-01
  • 2020-04-13
  • 2010-10-14
  • 1970-01-01
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多