繁体   English   中英

如何执行Azure Queue触发的大量持久函数?

[英]How to execute a lot of durable functions triggered by Azure Queue?

简而言之,我们的任务是处理大量输入消息。

为了解决这个问题,我们决定使用 Azure 队列存储和 Azure Functions。 我们有类似于以下代码的 Azure Functions 结构:

队列触发功能

[FunctionName("MessageControllerExecutor")]
public static async void Run(
    [QueueTrigger(QUEUE_NAME, Connection = QUEUE_CONNECTION_NAME)]string queueMessage,
    [OrchestrationClient] DurableOrchestrationClient client,
    TraceWriter log)
{
    await client.StartNewAsync("MessageController", queueMessage);
}

耐用功能

[FunctionName("MessageController")]
public static async void Run(
    [OrchestrationTrigger] DurableOrchestrationContext context,
    TraceWriter log)
{
    if (!context.IsReplaying) log.Warning("MessageController started");

    var function1ResultTask = context.CallActivityAsync<ResultMessage>("Function_1", new InputMessage());
    var function2ResultTask = context.CallActivityAsync<ResultMessage>("Function_2", new InputMessage());

    await Task.WhenAll(function1ResultTask, function2ResultTask);

    // process Function_1 and Function_2 results
    // ...
}

简单活动函数示例

[FunctionName("Function_1")]
public static ResultMessage Run(
    [ActivityTrigger] DurableActivityContext activityContext,
    TraceWriter log)
{
    var msg = activityContext.GetInput<InputMessage>();
    int time = new Random().Next(1, 3);
    Thread.Sleep(time * 1000);

    return new ResultMessage()
    {
        Payload = $"Function_1 slept for {time} sec"
    };
}

MessageControllerExecutor在队列中接收到新项目时触发。 MessageController是一个 Durable Function,它使用一些简单的活动函数来处理每条消息。

当我们将消息推送到队列时, MessageControllerExecutor函数会立即启动并异步触发MessageController并传递消息,因此这按预期工作。

但是我们面临着这个问题。 并非所有MessageController函数实例都运行。

例如,我们将 100 条消息推送到队列中,但只有大约 10-20% 的消息被MessageController处理。

某些消息未处理或处理延迟很长时间。 看起来持久函数未能启动 б,尽管没有抛出异常。

我们有几个问题:

  1. 这个具有队列触发和持久函数的解决方案是否正确处理消息队列,或者有更好的方法来触发队列的持久函数?
  2. 运行持久函数是否有任何限制?
  3. 可以同时执行多少个持久函数?
  1. 是的,这是开始编排的完全有效的方式!
  2. 当然, 这里有一些关于架构的细节,因为它与性能和可伸缩性有关
  3. 您可能想在这里问的是:可以同时执行单个持久函数定义的多少个编排实例 这确实是一个非常重要的方面需要理解。 编排功能本身是单线程,并且根据我上面提供的规模链接,在一组控制队列之间进行平衡。 您可以阅读该文档以获取更多信息,但最重要的是,除了在编排功能中进行实际编排之外,您不想做任何其他工作,因为它们是您对可扩展性的限制。 它是业务流程操作函数,其行为与任何其他 Azure 函数类似,并且对其可扩展性几乎没有限制。

为了我理解的简洁起见,您确实从上面的问题中的编排触发器中删除了一些代码,但是在await Task.WhenAll(...)之后您到底在做什么? 如果它包含任何类型的重要处理,您应该真正将其分配给第三个操作函数(例如Function_3 )来执行,然后简单地从编排函数返回结果。

更新:我刚刚注意到你的函数被定义为async void 如果我不得不猜测,这实际上会导致运行时出现问题。 您可以尝试将其更改为async Task并查看您的问题是否消失吗? 作为一般规则,在 .NET 中async void将方法定义为async void

德鲁答案的一些扩展。 正如文档所述,您不应使用 Thread.Sleep(),而应使用 CreateTimer Api。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM