c# - 如何执行Azure队列触发的大量持久函数?

标签 c# azure azure-functions

简单来说,我们的任务是处理大量输入消息。

为了解决这个问题,我们决定使用 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 是一个持久函数,它使用一些简单的事件函数来处理每条消息。

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

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

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

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

我们有几个问题:

  1. 这个具有队列触发和持久功能的解决方案是否正确 处理消息队列或者有更好的方法通过队列触发持久函数?
  2. 运行持久函数有任何限制吗?
  3. 可以同时执行多少个持久函数?

最佳答案

  1. 是的,这是启动编排的完全有效的方式!
  2. 当然,here's some details on the architecture as it relates to performance and scalability .
  3. 认为您在这里可能想问的是:可以同时执行单个持久函数定义的多少个编排实例?这确实是一个需要理解的非常重要的方面。编排函数本身是单线程,并且根据我上面给出的规模链接,在一组控制队列之间实现平衡。您可以阅读该文档以获取更多信息,但底线是您不想在编排功能中执行除实际编排之外的任何工作,因为它们限制了可扩展性。编排操作函数的行为与任何其他 Azure 函数类似,并且其可扩展性几乎没有限制。

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

更新:我刚刚注意到您的函数被定义为async void。如果我不得不猜测,这实际上会导致运行时出现问题。您可以尝试将其更改为异步任务,看看您的问题是否消失?作为一般规则defining methods as async void is frowned upon in .NET .

关于c# - 如何执行Azure队列触发的大量持久函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48591061/

相关文章:

C# 反序列化列表计数为零

c# - C# 替换字符串的部分内容

azure - 我一直在努力在 Azure Synapse Analytics 上找到任何相关文档,以使用 CLI 为 Azure KeyVault 提供链接服务

Azure Application Insights - 为异常创建深层链接?

c# - Azure Function 2.0 绑定(bind)属性的 ServiceBusTrigger

c# - 如何获取使用局部变量的 ConstantExpression 的值?

c# - 如何 : Convert anonymous method to VB. NET

azure - 通过 terraform 创建 azuread_application_password 时无法输出 client_secret

c# - Azure功能:我无法选择消费计划

node.js - 无法使用 Azure 函数找到模块 grpc_node.node