Spring AI Alibaba Graph + DDD 改造實(shí)戰(zhàn):把串行 Skill 鏈升級為可恢復(fù)、可回放、可治理的 Agent 工作流
一、寫在前面:這次改造到底解決了什么問題
在很多 AI 應(yīng)用的早期階段,工程實(shí)現(xiàn)都會(huì)先走一條“能跑就行”的路徑:
把幾個(gè) Skill(RAG 檢索、內(nèi)容生成、合規(guī)檢查、計(jì)費(fèi)結(jié)算、發(fā)布)按順序串起來,形成一個(gè)線性的執(zhí)行鏈。
這種方式在 MVP 階段非常高效,但當(dāng)業(yè)務(wù)進(jìn)入“多場景、多策略、高并發(fā)、強(qiáng)可觀測”的階段后,線性鏈路很快觸頂:
- 分支決策復(fù)雜:無召回、高風(fēng)險(xiǎn)、超預(yù)算都需要分支,線性代碼膨脹明顯;
- 失敗恢復(fù)困難:某個(gè)節(jié)點(diǎn)失敗只能重跑整條鏈路,成本高且不可控;
- 觀測粒度粗:只能知道“成功/失敗”,很難定位到底是哪個(gè)節(jié)點(diǎn)慢、哪個(gè)節(jié)點(diǎn)貴;
- 演進(jìn)成本高:新增一個(gè)分支策略,往往牽一發(fā)動(dòng)全身;
- 運(yùn)維排障困難:沒有流程回放與事件軌跡,線上問題靠日志“猜”。
這篇文章總結(jié)的是一套已經(jīng)落地的改造方案:
基于 Spring AI Alibaba Graph 思路 + DDD 分層,把原串行 Skill 鏈升級為狀態(tài)驅(qū)動(dòng)的 Graph 工作流系統(tǒng)。
目標(biāo)不是“炫技”,而是非常工程化的四件事:
- 可治理:路由策略、預(yù)算策略、場景策略可配置;
- 可恢復(fù):關(guān)鍵節(jié)點(diǎn) checkpoint,支持 resume;
- 可觀測:節(jié)點(diǎn)指標(biāo) + 事件流 + 回放接口;
- 可灰度:特性開關(guān) + 場景白名單 + 可回滾。
二、改造目標(biāo)與邊界
2.1 業(yè)務(wù)目標(biāo)
- 支撐母嬰內(nèi)容生產(chǎn)場景下的穩(wěn)定 AI 生成鏈路;
- 處理典型異常分支:
- 無召回 -> 通用生成;
- 高風(fēng)險(xiǎn) -> 安全改寫(MVP);
- 超預(yù)算 -> 短答/拒答;
- 在可控成本前提下,提高吞吐與可維護(hù)性。
2.2 技術(shù)目標(biāo)
-
統(tǒng)一 Graph 執(zhí)行入口,替換串行適配器;
好處是流程編排、分支決策、重試恢復(fù)都在同一套機(jī)制里,避免多套執(zhí)行邏輯并存。
-
引入運(yùn)行態(tài)狀態(tài)機(jī)模型;
用
AgentGraphState表示一次執(zhí)行在“當(dāng)前節(jié)點(diǎn)、累計(jì) token、節(jié)點(diǎn)輸出、狀態(tài)”等維度的實(shí)時(shí)狀態(tài)。
這讓流程從“代碼順序驅(qū)動(dòng)”變成“狀態(tài)驅(qū)動(dòng)”,天然支持分支、恢復(fù)和回放。 -
建立 checkpoint/metrics/events 三類運(yùn)行數(shù)據(jù)
- heckpoint`:關(guān)鍵節(jié)點(diǎn)快照,用于失敗后斷點(diǎn)恢復(fù);
-
metrics:每節(jié)點(diǎn)耗時(shí)、token、重試、成功失敗,用于性能和成本治理; -
events:節(jié)點(diǎn)執(zhí)行與分支事件軌跡,用于問題定位和過程解釋。
三者合起來,就是“可恢復(fù) + 可觀測 + 可解釋”。
提供 replay/resume 接口用于運(yùn)維與排障。
2.3 改造邊界(MVP)
- 先不追求全自動(dòng)策略學(xué)習(xí);
- 先實(shí)現(xiàn) SafeRewrite,HumanReview 預(yù)留擴(kuò)展點(diǎn);
- 先覆蓋主鏈路 + 關(guān)鍵分支 + 恢復(fù)能力;
- 與既有系統(tǒng)并存,支持按場景灰度。
2.4 先引入概念:LangChain 是什么
如果把大模型應(yīng)用比作“后端系統(tǒng)”,LangChain 更像一個(gè)“應(yīng)用開發(fā)框架層”:
- 把模型調(diào)用、Prompt 模板、記憶、工具調(diào)用、檢索等能力做統(tǒng)一抽象;
- 提供“鏈(Chain)”思想,把多個(gè)步驟串聯(lián)成一個(gè)執(zhí)行單元;
- 降低不同模型廠商接入成本,便于快速迭代原型。
一句話理解:
LangChain 解決的是“如何更快組織 LLM 應(yīng)用能力”。
2.5 再引入概念:LangGraph 是什么
LangGraph 可以理解為 LangChain 在復(fù)雜流程場景下的增強(qiáng):
當(dāng)你的應(yīng)用不再是線性步驟,而是“有狀態(tài) + 有分支 + 可恢復(fù) + 可回放”的流程時(shí),Graph 思想更合適。
LangGraph 的核心機(jī)制包括:
- 狀態(tài)對象貫穿整個(gè)流程;
- 節(jié)點(diǎn)執(zhí)行與路由決策分離;
- 支持條件分支與循環(huán);
- 支持 checkpoint 與中斷恢復(fù);
- 更適合 Agent 系統(tǒng)、長流程編排、多工具協(xié)同。
一句話理解:
LangGraph 解決的是“復(fù)雜 Agent 流程如何工程化落地”。
2.6 為什么在 Java 體系選 Spring AI Alibaba Graph
在寶媽 AI 視頻平臺 Java 版本里,技術(shù)棧以 Spring Boot + DDD 為主,最終采用 Spring AI Alibaba Graph 路線,原因是:
- 與 Spring 生態(tài)天然融合(配置、依賴注入、AOP、事務(wù));
- 更容易與現(xiàn)有模塊(RAG、發(fā)布、計(jì)費(fèi)、合規(guī))整合;
- 對團(tuán)隊(duì)而言學(xué)習(xí)和維護(hù)成本更低;
- 既能借鑒 LangChain/LangGraph 思想,又符合 Java 工程落地習(xí)慣。
可用下面這個(gè)映射去理解三者關(guān)系:
- LangChain:能力編排思想(Prompt/Tool/Retrieval 組織方式)
- LangGraph:狀態(tài)流轉(zhuǎn)思想(節(jié)點(diǎn)、路由、恢復(fù)、回放)
- Spring AI Alibaba Graph:Java/Spring 體系下的工程實(shí)現(xiàn)路徑
三、整體架構(gòu):從“線性調(diào)用器”到“狀態(tài)驅(qū)動(dòng)編排器”
3.1 架構(gòu)分層(DDD)
本次拆分遵循 DDD 的“用例編排 / 領(lǐng)域規(guī)則 / 基礎(chǔ)設(shè)施適配”原則:
-
Domain(領(lǐng)域?qū)樱?/strong>
- 狀態(tài)模型:
AgentGraphState - 策略服務(wù):
GraphRoutePolicy、GraphBudgetPolicy、GraphScenarioPolicy - 查詢策略:
GraphEventQueryPolicy - 端口:
GraphExecutorPort、GraphRuntimeGateway、GraphRunEventHook
- 狀態(tài)模型:
-
Application(應(yīng)用層)
- 用例入口:
GraphRunApplicationService - 流程編排:
GraphFlowOrchestrator - 節(jié)點(diǎn)協(xié)議:
GraphNodeHandler+ 各具體節(jié)點(diǎn)處理器 - 回放能力:
GraphReplayApplicationService
- 用例入口:
-
Infrastructure(基礎(chǔ)設(shè)施層)
- 網(wǎng)關(guān)適配:
GraphRuntimeGatewayAdapter - 持久化:Mapper + DO(checkpoint、node_metric、event)
- 事件鉤子:日志鉤子 + 持久化鉤子
- Web 觸發(fā):
AgentGraphReplayController
- 網(wǎng)關(guān)適配:
3.2 寶媽 AI 視頻平臺(Java 版)模塊功能總覽
按“模塊職責(zé) + 輸入輸出 + 邊界”來講。
3.2.1 bootstrap(啟動(dòng)與系統(tǒng)裝配)
- 職責(zé):應(yīng)用啟動(dòng)、配置裝配、攔截器注冊、Mapper 掃描;
-
關(guān)鍵點(diǎn):統(tǒng)一讀取
application.yml中 Graph 開關(guān)、預(yù)算、場景白名單配置; - 邊界:不寫業(yè)務(wù)流程,只做系統(tǒng)集成與基礎(chǔ)設(shè)施入口。
3.2.2 common(通用能力)
- 職責(zé):通用異常、響應(yīng)包裝、Prompt 規(guī)則內(nèi)核、基礎(chǔ)工具;
-
關(guān)鍵點(diǎn):
BaomaPromptKernel、GlobalPromptRules承擔(dān) Prompt Guard 基礎(chǔ)能力; - 邊界:與具體業(yè)務(wù)場景解耦,供各業(yè)務(wù)模塊復(fù)用。
3.2.3 module-ai(AI 通用域)
- 職責(zé):承載 AI 運(yùn)行記錄與核心 AI 應(yīng)用服務(wù);
-
關(guān)鍵點(diǎn):
agent_run主記錄落在這里,Graph 改造后擴(kuò)展 graph 元字段; - 邊界:偏“AI 領(lǐng)域通用能力”,不承接具體圖編排細(xì)節(jié)。
3.2.4 module-rag(檢索增強(qiáng))
- 職責(zé):向量檢索、召回、壓縮、證據(jù)組織;
-
關(guān)鍵點(diǎn):對接 Milvus/Embedding;在 Graph 中對應(yīng)
RagRetrieve與RagCompress相關(guān)能力; - 邊界:只負(fù)責(zé)“找什么、怎么壓縮”,不負(fù)責(zé)最終生成策略。
3.2.5 module-publish(內(nèi)容生產(chǎn)與技能體系)
- 職責(zé):維護(hù) Skill 注冊與執(zhí)行能力,承接內(nèi)容生成鏈路;
-
關(guān)鍵點(diǎn):原串行
AiSkillExecutorAdapter從這里起步,后被 Graph 適配層接管流轉(zhuǎn); - 邊界:保留技能實(shí)現(xiàn),不直接主導(dǎo)流程編排。
3.2.6 module-token-billing(成本治理)
- 職責(zé):token 計(jì)量、扣費(fèi)、預(yù)算相關(guān)能力;
-
關(guān)鍵點(diǎn):Graph 的
TokenSettle節(jié)點(diǎn)在流程末端統(tǒng)一結(jié)算; - 邊界:只做計(jì)費(fèi)邏輯,不干預(yù)生成內(nèi)容語義。
3.2.7 module-agent-graph(本次改造核心模塊)
- 職責(zé):把原線性 Skill 鏈升級為可編排、可恢復(fù)、可回放的 Graph 工作流;
-
關(guān)鍵點(diǎn):
- Port:
GraphExecutorPort、GraphRuntimeGateway - Application:
GraphRunApplicationService、GraphFlowOrchestrator - Node:
GraphNodeHandler+ 各節(jié)點(diǎn)實(shí)現(xiàn) - Policy:route/budget/scenario/event-query
- Replay:
GraphReplayApplicationService+AgentGraphReplayController
- Port:
- 邊界:負(fù)責(zé)編排與狀態(tài)推進(jìn),不侵入底層 Skill 的具體實(shí)現(xiàn)細(xì)節(jié)。
3.2.8 其他業(yè)務(wù)模塊(user/member/points/video 等)
- 職責(zé):用戶域、會(huì)員域、積分域、視頻域等業(yè)務(wù)上下文;
- 關(guān)鍵點(diǎn):通過 command/context 為 Graph 提供業(yè)務(wù)輸入;
- 邊界:保持領(lǐng)域邊界,不把流程編排邏輯帶回本域。
3.3 從 LangGraph 思想到 Spring AI Alibaba Graph 實(shí)現(xiàn)的映射
可以用下面這張映射表解釋“概念如何落地”:
-
State(狀態(tài)) ->
AgentGraphState -
Node(節(jié)點(diǎn)) ->
GraphNodeHandler體系 -
Edge/Router(邊) ->
GraphRoutePolicy+GraphScenarioPolicy -
Checkpoint(斷點(diǎn)) ->
agent_graph_checkpoint+resume -
Event/Trace(事件追蹤) ->
agent_graph_event+ replay API -
Tool Invocation(工具調(diào)用) ->
GraphRuntimeGateway.executeSkill(...)
3.4 運(yùn)行流程圖(主鏈路 + 分支)

這張圖的重點(diǎn)不在“節(jié)點(diǎn)名字”,而在三層能力:
- 主流程穩(wěn)定推進(jìn);
- 條件分支可插拔;
- 最終都收斂到
TokenSettle -> Return/SSE,保持出口一致性。
四、核心狀態(tài)模型:AgentGraphState 為什么是這次改造的中心
AgentGraphState 是整個(gè)圖執(zhí)行過程的“單一事實(shí)來源(Single Source of Truth)”,典型字段如下:
-
runId:一次執(zhí)行鏈路唯一標(biāo)識(可直接作為 traceId); -
userId:歸屬用戶; -
conversationId:多輪會(huì)話關(guān)聯(lián)鍵; -
scenario:場景標(biāo)識(publish、chat、xhs 等); -
currentNode:當(dāng)前執(zhí)行節(jié)點(diǎn); -
nodeOutputs:節(jié)點(diǎn)輸出快照集合(流程上下文); -
tokenUsage:累計(jì) token 消耗; -
status:執(zhí)行狀態(tài)(RUNNING/SUCCESS/FAILED); -
error:失敗錯(cuò)誤信息; -
checkpointId:最近 checkpoint 標(biāo)識; -
retryCount:當(dāng)前節(jié)點(diǎn)重試次數(shù)。
為什么不用“散落變量”而要統(tǒng)一狀態(tài)對象
- 恢復(fù)執(zhí)行:checkpoint 需要完整狀態(tài)序列化;
- 節(jié)點(diǎn)解耦:節(jié)點(diǎn)只關(guān)心上下文,不關(guān)心調(diào)用棧細(xì)節(jié);
- 可回放:回放時(shí)必須有一致快照與事件錨點(diǎn);
- 可測試:狀態(tài)驅(qū)動(dòng)比線程局部變量更好寫測試。
五、數(shù)據(jù)模型與持久化:運(yùn)行軌跡如何落盤
5.1 agent_run 擴(kuò)展字段
在既有運(yùn)行表上增加 Graph 相關(guān)字段(統(tǒng)一入口視角):
-
graph_name:圖名稱(如baoma-agent-graph) -
graph_version:圖版本(灰度/回滾依據(jù)) -
checkpoint_id:最后一次 checkpoint -
last_node:最近執(zhí)行節(jié)點(diǎn) -
replayable_snapshot:可回放快照(壓縮/裁剪后)
5.2 新增表:checkpoint / metric / event
-
agent_graph_checkpoint(斷點(diǎn)快照,供resume反序列化后繼續(xù)跑)-
id:自增主鍵;列表/關(guān)聯(lián)用。 -
checkpoint_id:業(yè)務(wù)側(cè)斷點(diǎn)唯一 ID(UUID),與/checkpoints/{checkpointId}/resume入?yún)⒁恢拢?code>agent_run.checkpoint_id 也會(huì)回寫最近一次。 -
run_id:本次 Agent 圖運(yùn)行的 trace/run 標(biāo)識,與agent_run.trace_id對齊。 -
node_name:寫入 checkpoint 時(shí)所處的圖節(jié)點(diǎn)(如RAG_RETRIEVE、GENERATE);續(xù)跑時(shí)由此推算「下一節(jié)點(diǎn)」。 -
snapshot_json:可反序列化的完整快照(通常含GraphRunCommand+AgentGraphStateJSON),恢復(fù)即以此為起點(diǎn)。 -
create_time:落庫時(shí)間(審計(jì)與排序)。
-
-
agent_graph_node_metric(節(jié)點(diǎn)級 SLI/SLO:耗時(shí)、token、成?。?/p>-
id:自增主鍵。 -
run_id:歸屬運(yùn)行 ID。 -
node_name:被執(zhí)行的節(jié)點(diǎn)枚舉名(與GraphNodeName一致)。 -
duration_ms:該節(jié)點(diǎn)從進(jìn)入執(zhí)行到成功或耗盡重試的 wall time(毫秒),含重試退避;成功或最終失敗時(shí)各落庫一條指標(biāo)。 -
input_tokens/output_tokens:輸入/輸出 token 估計(jì)或計(jì)量(當(dāng)前實(shí)現(xiàn)里常與累計(jì)用量同一口徑落庫,便于后續(xù)拆維度)。 -
hit_count:擴(kuò)展計(jì)數(shù)位(如緩存命中、召回條數(shù)等,缺省 0)。 -
retry_count:該節(jié)點(diǎn)失敗前的已重試次數(shù)(與編排退避策略對應(yīng))。 -
status:該次節(jié)點(diǎn)執(zhí)行結(jié)果代碼,如SUCCESS/FAILED。 -
error_message:失敗時(shí)錯(cuò)誤摘要(成功一般為空)。 -
create_time:指標(biāo)寫入時(shí)間。
-
-
agent_graph_event(過程事件流,供回放 API 與排障)-
id:自增主鍵;分頁游標(biāo)常按id升/降序。 -
run_id:歸屬運(yùn)行 ID。 -
node_name:事件關(guān)聯(lián)節(jié)點(diǎn)(運(yùn)行級事件可為空)。 -
event_type:事件類型,如run-start、node-success、checkpoint-saved、run-failed等,供篩選用。 -
message:人類可讀短描述。 -
attributes_json:結(jié)構(gòu)化附加字段(tokenUsage、error、checkpointId 等)的 JSON。 -
event_time:業(yè)務(wù)事件發(fā)生時(shí)間(排序、時(shí)間窗查詢)。 -
create_time:落庫時(shí)間(可能與event_time略有先后)。
-
5.3 這三類表分別解決什么問題
- checkpoint:解決“斷點(diǎn)恢復(fù)”;
- metric:解決“性能與成本治理”;
- event:解決“過程可解釋與回放排障”。
六、編排與節(jié)點(diǎn)設(shè)計(jì):把“流程控制”從“能力執(zhí)行”中解耦
6.1 Orchestrator 的職責(zé)邊界
GraphFlowOrchestrator 只負(fù)責(zé):
- 節(jié)點(diǎn)執(zhí)行順序;
- 分支判斷;
- checkpoint 時(shí)機(jī);
- 重試與退避;
- 事件發(fā)布與指標(biāo)記錄。
不負(fù)責(zé)具體業(yè)務(wù)能力實(shí)現(xiàn)(例如真正的 RAG 或合規(guī)判定),這些通過 GraphRuntimeGateway 下沉到基礎(chǔ)設(shè)施適配層。
6.2 NodeHandler 策略化
每個(gè)節(jié)點(diǎn)一個(gè) GraphNodeHandler,例如:
InputGuardNodeHandlerRagRetrieveNodeHandlerGenerateNodeHandlerComplianceCheckNodeHandlerTokenSettleNodeHandlerReturnSseNodeHandler
優(yōu)勢:
- 新節(jié)點(diǎn)擴(kuò)展只需注冊 handler,不需要改大
switch; - 節(jié)點(diǎn)可單測;
- 節(jié)點(diǎn)失敗/重試行為統(tǒng)一由 Orchestrator 托管。
6.3 Support 拆分為領(lǐng)域服務(wù)
為降低“萬能工具類”聚合度,拆出了:
-
GraphContentAssemblyService:終態(tài)內(nèi)容拼裝、截?cái)啵?/li> -
GraphTokenEstimator:token 估算; -
GraphEventQueryPolicy:事件查詢契約歸一化(limit/order/cursor)。
這一步是典型 DDD 改造:
把“規(guī)則”抽到領(lǐng)域服務(wù),把“調(diào)用”留在應(yīng)用編排。
七、可靠性設(shè)計(jì):重試、checkpoint、resume 是怎么配合的
7.1 節(jié)點(diǎn)級重試
- 每節(jié)點(diǎn)有
maxAttempts; - 指數(shù)退避(
initialBackoffMs -> maxBackoffMs); - 重試與失敗寫入 metric + event;
- 最終失敗時(shí)更新運(yùn)行狀態(tài)并拋出。
7.2 checkpoint 策略
關(guān)鍵節(jié)點(diǎn)后持久化:
RAG_RETRIEVEGENERATECOMPLIANCE_CHECKTOKEN_SETTLE
每次 checkpoint 都會(huì)同步更新 agent_run.checkpoint_id/last_node,保證恢復(fù)入口最新。
7.3 resume 流程
- 根據(jù)
checkpointId找到最新快照; - 反序列化得到
state + command; - 計(jì)算下一節(jié)點(diǎn);
- 從下一節(jié)點(diǎn)繼續(xù)執(zhí)行;
- 收斂結(jié)果并更新 run。
這使得“偶發(fā)外部故障”不再導(dǎo)致“全鏈路重跑”。
八、觀測與回放:從“日志猜錯(cuò)”到“軌跡排障”
8.1 事件體系
典型事件:
run-startnode-successnode-retrynode-failedcheckpoint-savedbranch-safe-rewritebranch-general-generatebranch-short-answerrun-successrun-failed
8.2 回放接口(增強(qiáng)后)
當(dāng)前回放接口不僅返回 run/checkpoints/metrics,還支持事件篩選與分頁。
接口 1:獲取回放詳情
GET /api/v1/agent/graph/runs/{runId}/replay
支持參數(shù):
-
eventType(可選) -
nodeName(可選) -
fromTime(可選,ISO 時(shí)間) -
toTime(可選) -
cursor(可選,游標(biāo)) -
order(可選,asc|desc,默認(rèn)desc) -
limit(可選,默認(rèn) 200,范圍 1~1000)
請求示例
curl -G "http://localhost:8080/api/v1/agent/graph/runs/9f6a/replay" \
--data-urlencode "eventType=node-failed" \
--data-urlencode "order=desc" \
--data-urlencode "limit=50"
響應(yīng)示例(精簡)
{
"code": 0,
"msg": "ok",
"data": {
"run": {
"traceId": "9f6a",
"status": "FAILED",
"graphName": "baoma-agent-graph",
"graphVersion": "v1",
"lastNode": "GENERATE"
},
"checkpoints": [],
"metrics": [],
"events": [],
"eventsPage": {
"nextCursor": 10231,
"hasMore": true,
"returnedCount": 50,
"order": "desc",
"limit": 50
}
}
}
8.3 查詢契約治理(關(guān)鍵細(xì)節(jié))
GraphEventQueryPolicy 會(huì)統(tǒng)一歸一化參數(shù),避免不同層重復(fù)判斷導(dǎo)致行為不一致:
- 非法
order自動(dòng)回落desc; -
limit自動(dòng)鉗制到[1, 1000]; - 無效 cursor(<=0)自動(dòng)忽略。
這類“契約收斂”雖然看似小優(yōu)化,但對長期穩(wěn)定性非常重要。
九、接口示例:恢復(fù)執(zhí)行(Resume)
接口 2:從 checkpoint 恢復(fù)
POST /api/v1/agent/graph/checkpoints/{checkpointId}/resume
請求示例
curl -X POST "http://localhost:8080/api/v1/agent/graph/checkpoints/cp_abc123/resume"
響應(yīng)示例(精簡)
{
"code": 0,
"msg": "ok",
"data": {
"state": {
"runId": "9f6a",
"status": "SUCCESS",
"currentNode": "RETURN_SSE",
"tokenUsage": 932
},
"snapshots": {
"prompt": "請生成母嬰腳本",
"ragCompressed": "...",
"generate": {
"wechatContent": "..."
}
}
}
}
十、配置與灰度:如何做到“可上線、可回滾”
建議配置維度:
-
baoma.ai.graph.enabled:總開關(guān); -
baoma.ai.graph.scenario-whitelist:場景白名單; -
maxAttempts/initialBackoffMs/maxBackoffMs:重試參數(shù); -
defaultTokenBudget+scenarioTokenBudget:預(yù)算策略; -
allowSafeRewriteScenarios/allowGeneralFallbackScenarios/allowShortAnswerScenarios:分支許可。
灰度順序建議:
- 小流量場景開啟 Graph;
- 先開主鏈路,后開分支;
- 觀察 node metric 與 event;
- 達(dá)標(biāo)后擴(kuò)大場景;
- 留好一鍵回退到串行鏈路的能力。
十一、測試策略:別只測 happy path
最少覆蓋四類測試:
-
策略測試:
GraphRoutePolicy/GraphBudgetPolicy/GraphEventQueryPolicy - 編排測試:主鏈路 + 三大分支(無召回/高風(fēng)險(xiǎn)/超預(yù)算)
- 恢復(fù)測試:checkpoint -> resume -> 收斂成功
- 契約測試:回放接口參數(shù)邊界(order/limit/cursor/time window)
目前已覆蓋:
- 主鏈路與分支集成測試;
- resume 流程測試;
- 查詢策略歸一化測試;
- 事件分頁與排序能力落地。
十二、踩坑與復(fù)盤
12.1 典型坑
- 把所有邏輯堆進(jìn) Orchestrator,導(dǎo)致“巨型服務(wù)”;
- 事件查詢參數(shù)在控制器、應(yīng)用層、網(wǎng)關(guān)層分別處理,行為不一致;
- 只記錄失敗日志,不記錄分支決策事件,排障成本高;
- 沒有 checkpoint 粒度設(shè)計(jì),恢復(fù)要么太頻繁要么不夠用。
12.2 復(fù)盤結(jié)論
真正好用的 Graph 架構(gòu),不是“會(huì)畫圖”:
- 是規(guī)則有邊界(策略服務(wù));
- 是狀態(tài)可恢復(fù)(checkpoint);
- 是過程可解釋(event + replay);
- 是上線可灰度(feature flag + scenario whitelist)。
結(jié)語
這次改造最有價(jià)值的,不是“用了 Graph”這件事本身,而是建立了一條長期可演進(jìn)的工程主線:
狀態(tài)驅(qū)動(dòng) + 策略下沉 + 可恢復(fù) + 可觀測 + 可灰度。
當(dāng)業(yè)務(wù)繼續(xù)增長時(shí),你不需要重寫系統(tǒng),只需要在既有邊界內(nèi)擴(kuò)節(jié)點(diǎn)、擴(kuò)策略、擴(kuò)觀測,這就是 DDD 改造真正帶來的復(fù)利。