首页 > 解决方案 > 如何在 DevOps 管道中为长时间运行的 Azure Functions 使用回调?

问题描述

我有一个 Azure DevOps 发布管道,它部署了一个 Python Azure 函数,然后调用它。Python 函数做了一些繁重的工作,因此需要几分钟才能执行。

Invoke Azure Function 任务的完成事件有两个选项: Api ResponseCallback .0

使用Api Response时的最大响应时间是 20 秒,所以我需要使用Callback。好的。使用此文档,我实现了一个 Azure 函数,该函数立即返回一个 HTTPResponse,然后将完成数据发布到指定的端点。这是我的 Azure 函数的完整代码:

import logging
import time
import threading

import azure.functions as func

def main(req: func.HttpRequest) -> func.HttpResponse:

    t = threading.Thread(target=do_work, args=(req,))
    t.start()

    return func.HttpResponse("Succeeded", status_code=200)

def do_work(req: func.HttpRequest):

    logging.info ("Starting asynchronous worker task")

    #time.sleep(21)

    try:
        planUrl = req.headers["PlanUrl"]
        projectId = req.headers["ProjectId"]
        hubName = req.headers["HubName"]
        planId = req.headers["PlanId"]
        taskInstanceId = req.headers["TaskInstanceId"]
        jobId = req.headers["JobId"]

        endpoint = f"{planUrl}/{projectId}/_apis/distributedtask/hubs/{hubName}/plans/{planId}/events?api-version=2.0-preview.1"
        body = {
            "name": "TaskCompleted",
            "taskId": taskInstanceId,
            "jobId": jobId,
            "result": "succeeded"
        }
        logging.info(endpoint)
        logging.info(body)
        requests.post(endpoint, data=body)

    except:
        pass

    finally:
        logging.info ("Completed asynchronous worker task")

现在,Invoke Azure Function 任务不会超时,但也不会完成。看起来它正在等待其他事情发生:

等死

不知道我应该在这里做什么。我也在GitHub 上关注这个线程,但它并没有导致解决方案。

标签: azurecallbackazure-functions

解决方案


除非您使用的是 Durable 函数(此处不需要),否则 Azure Functions 不支持将后台作业作为此类函数执行的一部分。

一旦函数返回响应,该通道就会以任何后台操作都无法按预期工作的方式关闭(异常 - 持久函数)。

如果您需要像这样异步工作并且您可以不等待响应,推荐的方法是使用多个函数。

在这种情况下,您的 HttpTrigger 可以将消息放入队列(或任何其他消息传递服务)并立即返回响应。然后,您将有一个队列触发器(或其他基于事件的触发器)来从队列(或任何此类消息传递服务)中获取事件并进行繁重的工作,一旦完成,就可以在您的示例中发布到该端点。

如果您只想使用一个功能来实现这一点,那么从您的 devops 管道中,您可以直接将消息发送到消息传递服务并让您的功能触发该功能。

希望这可以帮助!


推荐阅读