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

基于Azure Functions扩展OptaPlanner的扩容配置咨询

OptaPlanner迁移至Azure Function扩容失效、性能下降问题求助

我正在尝试将OptaPlanner项目迁移上云,部署为Azure Function,核心目标是提升系统扩展能力,支撑公司并行处理更多求解任务。

背景:当前我们的项目基于optaplanner-spring-boot-starter Maven包运行在Docker容器中,单任务串行求解场景下运行稳定。但我们需要大幅提升系统扩展性,在有限时间内完成更多求解任务,因此希望依托云方案补充所需的额外CPU算力。

我基于optaplanner-core Maven包结合现有方案的自定义领域对象搭建了概念验证版Azure Function,采用HTTP触发器,目前可正常返回求解结果,但性能出现严重下降。我原本计划升级消费计划以指定CPU与内存配置要求,却发现Azure并未按预期扩容新增实例,导致OptaPlanner出现资源竞争、自我阻塞的问题。

以下是核心驱动代码:

@FunctionName("solve")
public HttpResponseMessage run(
    @HttpTrigger(name = "req", methods = {HttpMethod.POST },authLevel = AuthorizationLevel.FUNCTION) 
    HttpRequestMessage<Schedule> request,
    final ExecutionContext context) {

    SolverConfig config = SolverConfig.createFromXmlResource("solverConfig.xml");
    
    //SolverManagerConfig managerConfig = new SolverManagerConfig().withParallelSolverCount("2");
    //SolverManagerConfig managerConfig = new SolverManagerConfig().withParallelSolverCount("10");
    //SolverManagerConfig managerConfig = new SolverManagerConfig().withParallelSolverCount("400");
    SolverManagerConfig managerConfig = new SolverManagerConfig().withParallelSolverCount("AUTO");
    
    SolverManager<Schedule, UUID> solverManager = SolverManager.create(config ,managerConfig);
    
    SolverJob<Schedule, UUID> solverJob = solverManager.solve(UUID.randomUUID(), problem);

    // 阻塞等待求解结束
    Schedule solution = solverJob.getFinalBestSolution();

    return request.createResponseBuilder(HttpStatus.OK)
        .header("Content-Type", "application/json")
        .body(solution)
        .build();
}

待解决问题

  • 如何配置Azure平台,实现每次HTTP调用都触发新实例扩容,让每个求解任务无需竞争资源?我已尝试通过设置FUNCTIONS_WORKER_PROCESS_COUNT=1、maxConcurrentRequests=1进行配置,也多次调整OptaPlanner的parallelSolverCount和moveThreadCount参数取值,均未观察到明显效果。
  • 在Azure场景下是否应该搭配Quarkus使用,而非采用core Maven包?我查阅到OptaPlanner核心维护者Geoffrey De Smet曾在技术回复中提到“AWS Lambda(无服务器)场景下推荐使用Quarkus”。

我已有20余年未接触Java开发,同时对Azure Functions、OptaPlanner均不熟悉,恳请大家提供相关参考建议。
非常感谢!


回答

针对Azure扩容配置问题

你之前的配置没生效核心是没匹配Azure Function的扩容判断逻辑,按以下顺序调整即可:

  • 首先把OptaPlanner的parallelSolverCount固定设为1,moveThreadCount设为NONE。单实例内跑多求解器或者多移动线程只会抢占CPU,反而会让Azure的扩容逻辑误判当前实例负载没到阈值,不会触发新实例启动。你的目标是单实例只跑1个求解任务,所有并行能力靠实例横向扩容实现,不要在单实例内做并行配置。
  • 不要用默认的消费计划,换成弹性高级计划EP1及以上规格。消费计划的HTTP触发器扩容有明显冷启动延迟,且扩容粒度按每秒请求数阶梯上涨,做不到请求到达就立刻启动新实例;高级计划支持配置预热预留实例,扩容响应速度快很多。
  • 在host.json里除了设置maxConcurrentRequests=1,还要把functionTimeout调到和你求解任务最长耗时匹配(消费计划最长支持10分钟,高级计划最长支持60分钟,超时会强制中断求解),同时在扩缩容配置项里把perInstanceConcurrency硬设为1,关闭单实例的请求排队逻辑。
  • 应用设置里除了FUNCTIONS_WORKER_PROCESS_COUNT=1,还要新增WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT配置,值设为你需要的最大并行求解任务数。默认消费计划下这个阈值只有10-20,不手动修改的话就算请求堆积也不会扩容到超过上限。
  • 你现在的代码里每次请求都新建SolverManager是非常重的操作,要把SolverConfig和SolverManager的初始化放到函数静态全局区,只在实例冷启动时初始化一次,不要每次请求都重新创建。这部分初始化开销会占掉单实例30%以上的CPU和启动时间,直接拖慢求解速度还会干扰扩容判断。

针对Quarkus选型问题

无服务器场景下确实推荐搭配Quarkus使用,原因非常直接:

  • Quarkus编译后的native镜像启动速度比传统Java应用快10倍以上,冷启动时间从十几秒降到1秒内,不会出现实例刚扩容起来还在启动JVM、加载类,请求就已经超时的问题。
  • Quarkus的OptaPlanner扩展做了GraalVM原生适配,运行时内存占用比直接用optaplanner-core低50%以上,同样规格的Function实例可以支撑更复杂的求解任务,不会因为内存不足被Azure强制回收实例。
  • 就算不折腾native编译,用Quarkus的JVM模式运行,启动速度、内存占用表现也比你现在直接用core包更好,不需要改动太多求解逻辑,只需要把现有领域类和求解配置迁移到Quarkus工程即可。

额外优化建议

不建议用同步HTTP触发器直接跑长耗时求解任务,HTTP连接本身有多层超时限制,就算把函数超时调大,前端负载均衡、客户端也可能提前断连。更稳妥的方案是用存储队列/服务总线队列做触发器,HTTP请求只负责把求解任务丢进队列、立刻返回任务ID,队列触发器自动触发新实例跑求解,求解完成后把结果存入数据库/存储,前端通过轮询获取结果。这种模式下Azure的队列扩容逻辑比HTTP触发器精准很多,基本不会出现请求堆积不扩容的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 06:27:18