Spring AI Alibaba 1.x 系列【61】Graph 持久化执行

文章目录

  • [1. 概述](#1. 概述)
  • [2. 应用场景与核心价值](#2. 应用场景与核心价值)
    • [2.1 典型应用场景](#2.1 典型应用场景)
    • [2.2 核心价值](#2.2 核心价值)
  • [3. 启用前置条件](#3. 启用前置条件)
  • [4. 确定性与一致性重放规范](#4. 确定性与一致性重放规范)
    • [4.1 重放运行逻辑](#4.1 重放运行逻辑)
    • [4.2 强制封装操作类型](#4.2 强制封装操作类型)
    • [4.3 编码设计准则](#4.3 编码设计准则)
  • [5. 持久化配置方式](#5. 持久化配置方式)
    • [5.1 编译阶段配置](#5.1 编译阶段配置)
    • [5.2 执行阶段配置](#5.2 执行阶段配置)
    • [6. 业务编码规范与示例优化](#6. 业务编码规范与示例优化)
    • [6.1 不推荐写法](#6.1 不推荐写法)
    • [6.2 规范优化写法](#6.2 规范优化写法)
  • [7. 工作流恢复机制](#7. 工作流恢复机制)
    • [7.1 三大恢复应用场景](#7.1 三大恢复应用场景)
    • [7.2 异常恢复代码示例](#7.2 异常恢复代码示例)
    • [7.3 恢复起始规则](#7.3 恢复起始规则)
  • [8. 生产最佳实践](#8. 生产最佳实践)
  • [9. 长耗时任务实战案例](#9. 长耗时任务实战案例)
  • [10. 文档总结](#10. 文档总结)

1. 概述

持久化执行是工作流核心运行保障技术,流程运行至关键节点时自动留存执行进度、状态数据与节点位置信息,支持任务暂停、异常中断、服务重启后从断点位置接续运行,无需重复执行历史步骤。

Spring AI Alibaba Graph 依托内置持久化层与检查点机制,自动保存每一步运行状态。无论故障类型为系统宕机、网络波动、LLM 调用超时,或是人工介入暂停流程,均可依据历史快照精准恢复任务执行。

功能开启提示:项目中配置检查点器后,即可自动启用持久化执行能力,全程支持随时暂停、异常重试、断点续跑。

2. 应用场景与核心价值

2.1 典型应用场景

  1. 人在回路交互:流程暂停等待人工审核、数据修正、指令确认,完成干预后继续流转
  2. 长周期运行任务:批量数据处理、多轮智能问答、复杂业务编排等耗时任务
  3. 异常容错处理:第三方接口超时、程序报错、服务重启等意外中断场景

2.2 核心价值

  • 断点续执:依托历史快照恢复流程,规避重复运算,节约系统资源
  • 超长时效留存:间隔数日仍可正常恢复执行,适配离线业务场景
  • 执行链路溯源:完整记录运行轨迹,支持状态回溯与问题排查
  • 高可靠运行:抵御各类中断故障,保障业务流程最终闭环
  • 灵活人工干预:预留操作入口,满足人工校验、业务调整需求

3. 启用前置条件

使用持久化执行功能,必须满足三项基础要求:

  1. 配置检查点器:注册状态存储实例,负责快照数据持久化保存
  2. 绑定唯一线程标识 :通过 threadId 区分独立任务实例,隔离不同流程运行数据
  3. 遵循确定性重放规则:特殊业务操作统一封装至节点内部,保障恢复执行结果一致

4. 确定性与一致性重放规范

4.1 重放运行逻辑

任务恢复时不会从代码中断行继续,而是以中断节点起始位置为起点,依次重放后续所有流程步骤,因此业务代码必须保证可稳定重复执行。

4.2 强制封装操作类型

以下操作必须独立封装至专属节点,禁止零散编写:

  1. 非确定性操作:随机数、时间戳、唯一标识生成类逻辑
  2. 副作用操作:API调用、文件读写、数据库增删改、消息推送等外部交互逻辑
  3. 高耗时操作:大模型调用、海量数据运算、第三方服务请求

4.3 编码设计准则

  1. 拆分独立职责:单个节点仅处理单一业务逻辑,多类副作用操作拆分为多个节点
  2. 隔离不确定逻辑:非固定结果代码统一收纳在节点内,执行结果存入全局状态
  3. 实现操作幂等性:重复执行操作不会产生脏数据、重复订单、冗余文件等异常结果

5. 持久化配置方式

5.1 编译阶段配置

构建编译图时注册检查点存储策略,全局定义持久化规则:

java 复制代码
import com.alibaba.cloud.ai.graph.CompileConfig;
import com.alibaba.cloud.ai.graph.CompiledGraph;
import com.alibaba.cloud.ai.graph.checkpoint.config.SaverConfig;
import com.alibaba.cloud.ai.graph.checkpoint.savers.MemorySaver;

SaverConfig saverConfig = SaverConfig.builder()
      .register(new MemorySaver())
      .build();

CompiledGraph graph = stateGraph.compile(
      CompileConfig.builder()
              .saverConfig(saverConfig)
              .build()
);

5.2 执行阶段配置

任务发起时指定唯一线程ID,绑定当前流程实例:

java 复制代码
import com.alibaba.cloud.ai.graph.CompiledGraph;
import com.alibaba.cloud.ai.graph.RunnableConfig;
import java.util.Map;
import java.util.UUID;

RunnableConfig config = RunnableConfig.builder()
      .threadId("long-running-task-" + UUID.randomUUID())
      .build();

graph.invoke(inputData, config);

6. 业务编码规范与示例优化

6.1 不推荐写法

副作用操作直接内嵌节点,任务恢复时会重复发起请求,引发业务异常:

java 复制代码
var callApi = node_async(state -> {
  String url = (String) state.value("url").orElse("");
  HttpClient client = HttpClient.newHttpClient();
  HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).build();
  HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
  return Map.of("result", response.body().substring(0,Math.min(100, response.body().length())));
});

6.2 规范优化写法

抽取通用业务服务,节点仅负责状态流转与逻辑编排,满足重放与幂等要求:

java 复制代码
import com.alibaba.cloud.ai.graph.StateGraph;
import static com.alibaba.cloud.ai.graph.action.AsyncNodeAction.node_async;
import java.net.http.*;
import java.net.URI;
import java.util.*;
import java.util.stream.Collectors;

// 通用HTTP请求服务,统一管理外部调用
class HttpRequestService {
  private final HttpClient client = HttpClient.newHttpClient();
  public String makeRequest(String url) throws Exception {
    HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).build();
    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    return response.body().substring(0, Math.min(100, response.body().length()));
  }
}

// 定义状态更新策略
KeyStrategyFactory keyStrategyFactory = () -> {
  Map<String, KeyStrategy> keyStrategyMap = new HashMap<>();
  keyStrategyMap.put("urls", new ReplaceStrategy());
  keyStrategyMap.put("results", new AppendStrategy());
  return keyStrategyMap;
};

// 标准化业务节点
var callApi = node_async(state -> {
  List<String> urls = (List<String>) state.value("urls").orElse(List.of());
  HttpRequestService httpService = new HttpRequestService();
  List<String> results = urls.stream()
      .map(httpService::makeRequest)
      .collect(Collectors.toList());
  return Map.of("results", results);
});

// 构建并运行状态图
StateGraph stateGraph = new StateGraph(keyStrategyFactory)
  .addNode("call_api", callApi)
  .addEdge(StateGraph.START, "call_api")
  .addEdge("call_api", StateGraph.END);

7. 工作流恢复机制

7.1 三大恢复应用场景

  1. 人工暂停恢复:流程手动中断,修改状态参数后重启执行
  2. 故障异常恢复:接口报错、程序异常后,复用线程标识重试任务
  3. 服务重启恢复:进程关闭重启,依据历史快照接续业务流程

7.2 异常恢复代码示例

java 复制代码
import com.alibaba.cloud.ai.graph.RunnableConfig;
import com.alibaba.cloud.ai.graph.CompiledGraph;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Logger logger = LoggerFactory.getLogger(RecoveryDemo.class);
String threadId = "error-recovery-thread";
RunnableConfig config = RunnableConfig.builder()
  .threadId(threadId)
  .build();

try {
  // 首次执行任务
  graph.invoke(inputData, config);
} catch (Exception e) {
  logger.error("任务执行异常,启动断点恢复", e);
  // 传入空参数,自动读取历史状态继续运行
  graph.invoke(null, config);
}

7.3 恢复起始规则

  1. 普通节点中断:从当前异常节点起始位置恢复执行
  2. 子流程中断:回溯至调用子图的父节点重新运行
  3. 快照生成时机:单个节点全部逻辑执行完毕后,才会保存检查点

8. 生产最佳实践

  1. 节点单一职责:拆分复杂业务,精简单个节点逻辑,便于故障定位与重试
  2. 严格保障幂等性:外部交互接口、数据写入操作兼容重复执行,规避业务隐患
  3. 精简状态数据:仅存储序列化基础数据,剔除大文件、网络连接等无效对象
  4. 完善异常捕获:节点内部拦截处理报错,避免整体流程无故终止
  5. 分片处理海量任务:大批量数据拆分批次执行,每批次完成留存快照
  6. 区分存储环境:测试环境使用MemorySaver,生产环境替换Redis、数据库持久化方案
  7. 完备日志监控:记录节点流转、状态变更信息,跟踪任务整体运行进度

9. 长耗时任务实战案例

适用于批量数据清洗、离线统计、文档批量解析等场景,支持中断后无缝续跑

java 复制代码
import com.alibaba.cloud.ai.graph.*;
import com.alibaba.cloud.ai.graph.action.AsyncNodeAction;
import com.alibaba.cloud.ai.graph.action.EdgeAction;
import com.alibaba.cloud.ai.graph.checkpoint.config.SaverConfig;
import com.alibaba.cloud.ai.graph.checkpoint.savers.MemorySaver;
import java.util.*;
import java.util.stream.IntStream;

// 状态策略配置
KeyStrategyFactory keyStrategyFactory = () -> {
  Map<String, KeyStrategy> keyStrategyMap = new HashMap<>();
  keyStrategyMap.put("items", new ReplaceStrategy());
  keyStrategyMap.put("processedCount", new ReplaceStrategy());
  keyStrategyMap.put("results", new AppendStrategy());
  return keyStrategyMap;
};

// 分批数据处理节点
var processData = AsyncNodeAction.node_async(state -> {
  List<String> items = (List<String>) state.value("items").orElse(List.of());
  int processedCount = (int) state.value("processedCount").orElse(0);
  int batchSize = 100;
  int end = Math.min(processedCount + batchSize, items.size());
  List<String> batch = items.subList(processedCount, end);
  List<String> processedResults = batch.stream()
      .map(item -> "Processed: " + item)
      .toList();
  return Map.of("processedCount", end, "results", processedResults);
});

// 循环终止判断条件
var checkComplete = EdgeAction.edge_async(state -> {
  int processedCount = (int) state.value("processedCount").orElse(0);
  List<String> items = (List<String>) state.value("items").orElse(List.of());
  return processedCount >= items.size() ? StateGraph.END : "process_data";
});

// 组装状态图
StateGraph stateGraph = new StateGraph(keyStrategyFactory)
  .addNode("process_data", processData)
  .addEdge(StateGraph.START, "process_data")
  .addConditionalEdges("process_data", checkComplete,
      Map.of(StateGraph.END, StateGraph.END, "process_data", "process_data"));

// 配置持久化与编译
SaverConfig saverConfig = SaverConfig.builder().register(new MemorySaver()).build();
CompiledGraph graph = stateGraph.compile(
  CompileConfig.builder().saverConfig(saverConfig).build()
);

// 启动长任务
String taskThreadId = "long-running-task-" + UUID.randomUUID();
RunnableConfig config = RunnableConfig.builder().threadId(taskThreadId).build();
List<String> largeDataSet = IntStream.range(0, 10000)
  .mapToObj(i -> "Item-" + i)
  .collect(Collectors.toList());
graph.invoke(Map.of("items", largeDataSet, "processedCount", 0), config);

10. 文档总结

持久化执行是 Spring AI Alibaba Graph 实现企业级稳定业务编排的核心能力,以检查点快照为数据载体,依托线程 ID 实现任务隔离,配合确定性重放机制保障恢复结果无误。

该能力完美适配人工交互、异常容错、超长任务三类核心业务场景,开发过程中只需完成检查点配置、线程标识绑定、副作用节点封装三项基础操作,即可让工作流具备断点续跑、故障恢复、状态溯源的工业级运行能力。

相关推荐
编程牛马姐2 小时前
2026年Reddit养号指南:养号四个阶段实操
python·spring·intellij-idea
muqsen2 小时前
Java 分布式相关面试题总结
java·开发语言·分布式
星浩AI2 小时前
(四)Hugging Face 与魔搭实战:模型下载、API 调用与本地推理
人工智能·深度学习·llm
大熊背2 小时前
双目拼接竖缝消除(ISP 分区锐化实操方案) 优化方案
人工智能·算法·双目拼接
放下华子我只抽RuiKe52 小时前
React 从入门到生产(六):路由与导航
前端·人工智能·深度学习·react.js·前端框架·html·claude code
byzh_rc2 小时前
[DL_Net从入门到入土] 生成对抗网络 GAN
人工智能·生成对抗网络·php
做个文艺程序员2 小时前
第02篇:搭建 ES 集群 + Spring Boot 整合实战——从 Docker Compose 到 Java 客户端全覆盖
java·spring boot·elasticsearch
猫头虎2 小时前
【Trea】Trea国内版|国际版|海外版下载|Mac版|Windows版|Linux下载配置教程
linux·人工智能·windows·macos·aigc·ai编程·agi
Jinkxs2 小时前
LoadBalancer- 简单限流策略:Nginx 基于连接 / 请求的限流实现
java·运维·nginx