OptaPlanner 7.x → 8.x 升级 Checklist 适用场景APS / 排程系统、使用 ConstraintStream 或 Drools DRL、依赖实时规划Real-time Planning参考来源OptaPlanner 发展方向与问题一、升级前评估必做[ ]确认当前版本当前 OptaPlanner 版本_______例如 7.44.0.Final是否使用 Drools DRL 评分✅ 是 / ❌ 否是否使用链式规划PlanningChain/PlanningVariable(graphType CHAINED)✅ 是 / ❌ 否是否使用VariableListener✅ 是 / ❌ 否是否使用实时规划SolverManager.addProblemChange()✅ 是 / ❌ 否[ ]确认目标版本计划升级到8.___.FinalSpring Boot 版本是否 ≥ 2.78.x 最低要求[ ]阅读官方迁移指南OptaPlanner 8 Migration Guide重点关注 ConstraintStream 与 Drools 的生命周期说明二、依赖与构建配置[ ]升级 OptaPlanner BOM / Dependencydependency groupIdorg.optaplanner/groupId artifactIdoptaplanner-core/artifactId version8.x.x.Final/version /dependency[ ]移除或升级 Drools 相关依赖若计划保留 Drools确认optaplanner-drools版本一致若计划迁移移除optaplanner-drools、kie-ci等依赖[ ]清理本地构建缓存Mavenmvn cleanGradlegradle clean build --refresh-dependencies三、API 迁移核心修改1. ConstraintProviderApsConstraintProvider.java[ ]penalize / reward 方法签名调整// 7.x .penalize(超时惩罚, HardSoftScore.ONE_HARD); // 8.x .penalize(HardSoftScore.ONE_HARD) .asConstraint(超时惩罚);[ ]统一约束命名规则所有约束均以asConstraint(xxx)结尾避免匿名约束便于调试与分数分析[ ]验证所有 ConstraintStream 流from()/join()/ifExists()行为是否变化是否存在因类型推断导致的编译错误2. VariableListener 包路径变更[ ]修改 import 语句// 7.x import org.optaplanner.core.impl.domain.variable.listener.VariableListener; import org.optaplanner.core.impl.score.director.ScoreDirector; // 8.x import org.optaplanner.core.api.domain.variable.VariableListener; import org.optaplanner.core.api.score.director.ScoreDirector;[ ]检查所有自定义 VariableListener文件名示例*VariableListener.java确认无impl包残留引用3. ScoreDirector API 变更[ ]字符串属性名 → 方法引用// 7.x scoreDirector.beforeVariableChanged(entity, planStartTime); scoreDirector.afterVariableChanged(entity, planStartTime); // 8.x scoreDirector.beforeVariableChanged(entity, Entity::getPlanStartTime); scoreDirector.afterVariableChanged(entity, Entity::getPlanStartTime);[ ]全局搜索关键词beforeVariableChangedafterVariableChangedvariableChanged四、实时规划Real-time Planning适配1. ProblemChange 接口统一[ ]确认所有实时变更逻辑已迁移到ProblemChangepublic class AddTaskProblemChange implements ProblemChangeSchedule { Override public void doChange(Schedule schedule, ScoreDirectorSchedule scoreDirector) { // ... } }[ ]移除旧版实时规划相关代码Solver.addEntity()Solver.removeEntity()Solver.addProblemFact()2. SolverManager Problem ID 治理⚠️ 重要参考博文SolverManager 存在 Problem ID 复用异常问题[ ]平台侧接管 Problem ID 生成客户端传入业务 ID如orderId平台生成内部problemIdUUID / 自增 ID[ ]接口层改造启动规划返回内部problemId查询 / 终止 / 实时变更使用内部problemId[ ]增加 Problem ID 清理机制规划完成后主动调用solverManager.close(solverJobId)避免异常中断导致状态残留五、链式规划与新特性评估1. 现有链模型CHAINED[ ]暂不迁移到PlanningListVariable确认当前链模型运行稳定8.x 新链模型尚未完全成熟参考博文[ ]验证 Shadow Variable 行为CustomShadowVariable监听器是否正常触发时间计算逻辑是否与之前一致2. 新特性试用可选[ ]PlanningListVariable仅限新模块明确标注为“实验性功能”准备回退方案[ ]IndexShadowVariable仅在非核心链路中试用六、Drools DRL 迁移长期必做Drools DRL 将在 OptaPlanner 9.x 移除[ ]制定 DRL → ConstraintStream 迁移计划优先级核心约束 次要约束 调试约束[ ]增量迁移每次迁移 1–2 条约束对比新旧分数结果一致性[ ]或评估 Incremental Java Score Calculation性能要求极高时考虑实现成本较高参考博文七、测试与验证[ ]单元测试所有 ConstraintProvider 测试通过边界条件空集合、单实体验证[ ]集成测试典型业务场景全量规划实时规划添加 / 删除任务验证[ ]回归测试与 7.x 在相同数据集上运行对比解的质量与分数构成允许分数结构变化但业务结果应一致[ ]性能测试规划耗时是否显著增加GC / CPU 使用率是否在可接受范围八、部署与回滚预案[ ]灰度发布先在非核心业务线启用 8.x观察 1–2 个迭代周期[ ]回滚方案Git tag / 分支保留 7.x 稳定版本数据库 schema 无破坏性变更如有需单独处理[ ]监控增强Solver 执行时长监控Problem ID 泄漏检测异常 SolverJob 自动清理九、升级完成确认[ ] 所有javax.*/impl包引用已清除[ ] 所有约束均有asConstraint()命名[ ] 实时规划功能经生产流量验证[ ] 团队已了解 8.x API 变化点[ ] 文档已更新架构图、API 说明附录常见搜索关键词用于全局替换beforeVariableChanged afterVariableChanged VariableListener ScoreDirector penalize( reward( impl.domain.variable impl.score.director✅ 预计修改工作量2–3 小时✅ 主要风险点SolverManager Problem ID 管理、新链模型成熟度✅ 推荐节奏先升级 稳定 API再逐步迁移 Drools