You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

排查Durable Functions并行运行仍缓慢的问题

问题描述

我们实现了基于Fan Out模式的Durable Orchestrator函数,用于将日期范围任务拆分为多段并行处理,代码如下:

[FunctionName("process-orchestration")]
public async Task ProcessOrchestrationAsync(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var runProcessEvent = context.GetInput<RunProcessDto>();

    var processStartedAt = context.CurrentUtcDateTime;

    // 1. 初始化流程
    var initialiseProcessResponseDto = await context.CallActivityAsync<InitialiseProcessResponseDto>
        ("initialise-process-activity", );

    // 2. 并行运行分段任务
    var tasks = new List<Task<RunProcessSegmentResponseDto>>();
    foreach (var runProcessRequestDto in initialiseProcessResponseDto.RunProcessRequestDtos)
    {
        var subTask = context.CallActivityAsync<RunProcessSegmentResponseDto>("run-process-segment-activity", runProcessRequestDto);
        tasks.Add(subTask);
    }

    await Task.WhenAll(tasks);

    // 3. 聚合结果
    var runProcessSegmentResponseDtos = new List<RunProcessSegmentResponseDto>();

    foreach (var eachTask in tasks)
    {
        var taskResult = eachTask.Result;
        runProcessSegmentResponseDtos.Add(taskResult);
    }

    var aggregateProcessResultDto = new AggregateProcessResultDto()
    {
        RunProcessRequestDto = new RunProcessRequestDto()
        {
            NoOfDays = runProcessEvent.NoOfDays,
        },
        RunProcessSegmentResponseDtos = runProcessSegmentResponseDtos
    };
    var runProcessResponseDto = await context.CallActivityAsync<RunProcessResponseDto>("aggregate-process-result-activity", aggregateProcessResultDto);

    // 4. 完成流程
    runProcessResponseDto.ProcessStartedAt = processStartedAt;
    runProcessResponseDto.ProcessFinishedAt = context.CurrentUtcDateTime;
    await context.CallActivityAsync<RunProcessResponseDto>("finalise-process-activity", runProcessResponseDto);
}

整体流程正常,但部分天数少的日期段处理耗时异常久,诊断数据如下:

开始日期: 03/07/2022 
结束日期: 01/10/2022 
总天数: 90

流程启动时间: 01/10/2022 10:02:48 GMT 
流程结束时间: 01/10/2022 11:41:51 GMT

分段1:
开始日期: 03/07/2022
结束日期: 18/07/2022 
启动时间: 01/10/2022 10:02:48
结束时间: 01/10/2022 11:41:36

分段2:
开始日期: 19/07/2022
结束日期: 03/08/2022 
启动时间: 01/10/2022 10:02:48
结束时间: 01/10/2022 11:37:26

分段3:
开始日期: 04/08/2022
结束日期: 19/08/2022 
启动时间: 01/10/2022 10:02:48
结束时间: 01/10/2022 11:35:59

分段4:
开始日期: 20/08/2022
结束日期: 04/09/2022 
启动时间: 01/10/2022 10:02:48
结束时间: 01/10/2022 11:17:13

分段5:
开始日期: 05/09/2022
结束日期: 20/09/2022 
启动时间: 01/10/2022 10:02:48
结束时间: 01/10/2022 10:19:05

分段6:
开始日期: 21/09/2022
结束日期: 01/10/2022 
启动时间: 01/10/2022 10:02:48
结束时间: 01/10/2022 10:14:03

我们已尝试以下优化但无改善:

  • 升级至最高规格Premium函数实例
  • 在host.json中配置并行限制:
"extensions": {
    "durableTask": {
      "hubName": "%HubName%"
    },
    "maxConcurrentActivityFunctions": 5,
    "maxConcurrentOrchestratorFunctions": 5
  },
  "functionTimeout": "-1"

请问还有哪些未考虑到的性能影响因素?


可能的性能影响因素
  • 数据分布不均:虽然日期段的天数一致,但不同时间段的业务数据量可能差异极大。比如7-8月的订单、日志等数据量远高于9月,导致对应分段的实际处理负载远超其他段,即使实例规格足够,也会因为数据量过大耗时更久。需要检查各分段对应的实际数据行数、计算量差异。

  • 外部资源争抢:活动函数依赖的外部资源(如数据库)可能存在连接池限制,多个并行任务同时争抢连接时,早期启动的分段可能因等待连接被阻塞,而后期启动的任务反而先获取到资源完成处理。需要检查数据库连接池配置,以及活动函数中是否有长时间的资源等待逻辑。

  • 活动函数内部低效逻辑:旧日期段的处理可能涉及特殊逻辑分支(如历史数据归档校验、旧业务规则计算),或者存在未优化的查询(如未使用索引、全表扫描)。比如7月的数据存储在归档表中,查询速度远慢于9月的在线表;或者针对旧数据的计算逻辑更复杂,导致耗时增加。需要单独测试不同日期段的活动函数执行耗时,定位具体瓶颈。

  • Durable Task Hub存储性能瓶颈:Durable Orchestrator的状态、事件存储在后端存储服务中,如果存储账户的IOPS、吞吐量达到限制,会导致任务状态更新、事件传递延迟,进而影响活动函数的调度效率。特别是多个并行任务同时更新状态时,存储的IO瓶颈会被放大。需要检查存储账户的性能指标是否达到阈值。

  • 外部依赖性能波动:活动函数可能依赖第三方API、缓存服务等外部资源,旧日期段的请求可能因为外部服务的限流、性能降级而变慢。比如调用历史数据查询接口时,响应速度远低于近期数据接口,导致分段处理耗时增加。需要监控活动函数中外部调用的响应时间。


内容的提问来源于stack exchange,提问作者Paul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 23:15:35