簡體   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