Azure Functions - 在另一个线程中运行长时间操作

8

我正在尝试使用Azure Functions解决方案实现文件转换。该转换可能需要很长时间,因此我不希望在调用服务器上等待响应。 我编写了一个立即返回响应的函数(以指示服务可用并开始转换),并在单独的线程中运行转换。回调URL用于发送转换结果。

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, Stream srcBlob, Binder binder, TraceWriter log)
{
    log.Info($"C# HTTP trigger function processed a request. RequestUri={req.RequestUri}");

    // Get request model
    var input = await req.Content.ReadAsAsync<ConvertInputModel>();

    //Run convert in separate thread
    Task.Run( async () => {
        //Read input blob -> convert -> upload output blob
        var convertResult = await ConvertAndUploadFile(input, srcBlob, binder, log);

        //return result using HttpClient
        SendCallback(convertResult, input.CallbackUrl); 
    });

    //Return response immediately
    return req.CreateResponse(HttpStatusCode.OK);
}

新任务破坏绑定的问题。访问参数时我遇到了异常。那么如何在单独的线程中运行长时间操作?或者这种解决方案完全错误?

我不知道Azure Functions的内部实现,但如果你能像那样运行后台任务,我会非常惊讶。你需要一个新的设计,比如将消息放在队列上,然后有另一个进程(比如Web Job)来接收它。 - Crowcoder
2个回答

18

在Azure Functions中,不推荐(或不支持)使用这种模式。特别是在消耗计划中运行时,由于运行时无法准确地管理函数的生命周期,并最终关闭服务。

这里推荐(并且广泛使用)的一种模式是将此工作排队以供另一个函数处理,该函数正在侦听该队列,并立即向客户端返回响应。

使用此方法,您实际上可以实现相同的功能,其中实际处理将以可靠和高效的方式异步完成(如果需要,可以受益于自动缩放以正确处理增加的负载)。

请注意,在使用消费计划时,函数超时为5分钟。如果预计处理时间更长,则需要在启用AlwaysOn的专用计划上运行函数。


5
有没有相关文档可以指引我阅读? - Adam Levitt
您还可以将执行时间增加到10分钟。https://learn.microsoft.com/zh-cn/azure/azure-functions/functions-scale#timeout - Jordan Simba
1
如果我的线程只需要1秒钟,是否仍然适用相同的规则,或者可以支持呢?我想要立即回复,而不是让调用者等待1秒钟。(并且我也不想等待长达10秒钟的队列触发器反应) - Niels Brinch
队列触发器函数根据文档(https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-queue-trigger?tabs=in-process%2Cextensionv5&pivots=programming-language-csharp)不会每10秒轮询一次:
  • 当找到一条消息时,运行时会等待100毫秒,然后检查是否有另一条消息。
  • 当没有消息时,它会等待约200毫秒再次尝试。
- Pieter

4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接