第 12 章:生产部署与性能优化
12.1 本章目标
学完本章你将能够:
- 了解 LangGraph Platform 和 LangGraph Server 的部署方式
- 掌握生产环境的 Checkpointer 和 Store 配置
- 学会错误处理、重试和并发控制
- 了解监控、日志和成本优化策略
12.2 核心概念
生产部署架构
#mermaid-svg-zVipmvY4UvaIvA9a{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-zVipmvY4UvaIvA9a .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-zVipmvY4UvaIvA9a .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-zVipmvY4UvaIvA9a .error-icon{fill:#552222;}#mermaid-svg-zVipmvY4UvaIvA9a .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-zVipmvY4UvaIvA9a .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-zVipmvY4UvaIvA9a .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-zVipmvY4UvaIvA9a .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-zVipmvY4UvaIvA9a .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-zVipmvY4UvaIvA9a .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-zVipmvY4UvaIvA9a .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-zVipmvY4UvaIvA9a .marker{fill:#333333;stroke:#333333;}#mermaid-svg-zVipmvY4UvaIvA9a .marker.cross{stroke:#333333;}#mermaid-svg-zVipmvY4UvaIvA9a svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-zVipmvY4UvaIvA9a p{margin:0;}#mermaid-svg-zVipmvY4UvaIvA9a .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-zVipmvY4UvaIvA9a .cluster-label text{fill:#333;}#mermaid-svg-zVipmvY4UvaIvA9a .cluster-label span{color:#333;}#mermaid-svg-zVipmvY4UvaIvA9a .cluster-label span p{background-color:transparent;}#mermaid-svg-zVipmvY4UvaIvA9a .label text,#mermaid-svg-zVipmvY4UvaIvA9a span{fill:#333;color:#333;}#mermaid-svg-zVipmvY4UvaIvA9a .node rect,#mermaid-svg-zVipmvY4UvaIvA9a .node circle,#mermaid-svg-zVipmvY4UvaIvA9a .node ellipse,#mermaid-svg-zVipmvY4UvaIvA9a .node polygon,#mermaid-svg-zVipmvY4UvaIvA9a .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-zVipmvY4UvaIvA9a .rough-node .label text,#mermaid-svg-zVipmvY4UvaIvA9a .node .label text,#mermaid-svg-zVipmvY4UvaIvA9a .image-shape .label,#mermaid-svg-zVipmvY4UvaIvA9a .icon-shape .label{text-anchor:middle;}#mermaid-svg-zVipmvY4UvaIvA9a .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-zVipmvY4UvaIvA9a .rough-node .label,#mermaid-svg-zVipmvY4UvaIvA9a .node .label,#mermaid-svg-zVipmvY4UvaIvA9a .image-shape .label,#mermaid-svg-zVipmvY4UvaIvA9a .icon-shape .label{text-align:center;}#mermaid-svg-zVipmvY4UvaIvA9a .node.clickable{cursor:pointer;}#mermaid-svg-zVipmvY4UvaIvA9a .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-zVipmvY4UvaIvA9a .arrowheadPath{fill:#333333;}#mermaid-svg-zVipmvY4UvaIvA9a .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-zVipmvY4UvaIvA9a .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-zVipmvY4UvaIvA9a .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zVipmvY4UvaIvA9a .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-zVipmvY4UvaIvA9a .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zVipmvY4UvaIvA9a .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-zVipmvY4UvaIvA9a .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-zVipmvY4UvaIvA9a .cluster text{fill:#333;}#mermaid-svg-zVipmvY4UvaIvA9a .cluster span{color:#333;}#mermaid-svg-zVipmvY4UvaIvA9a div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-zVipmvY4UvaIvA9a .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-zVipmvY4UvaIvA9a rect.text{fill:none;stroke-width:0;}#mermaid-svg-zVipmvY4UvaIvA9a .icon-shape,#mermaid-svg-zVipmvY4UvaIvA9a .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zVipmvY4UvaIvA9a .icon-shape p,#mermaid-svg-zVipmvY4UvaIvA9a .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-zVipmvY4UvaIvA9a .icon-shape .label rect,#mermaid-svg-zVipmvY4UvaIvA9a .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zVipmvY4UvaIvA9a .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-zVipmvY4UvaIvA9a .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-zVipmvY4UvaIvA9a :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 监控
数据库
LangGraph Server
客户端
Web/App 客户端
API Server
:2024
langgraph_sdk
PostgreSQL
Checkpointer + Store
LangSmith
追踪 + 监控
开发 vs 生产
| 对比维度 |
开发环境 |
生产环境 |
| Checkpointer |
MemorySaver |
PostgresSaver |
| Store |
InMemoryStore |
PostgresStore |
| LLM 调用 |
直连 API |
加缓存 + 重试 |
| 错误处理 |
打印日志 |
结构化日志 + 告警 |
| 部署方式 |
langgraph dev |
langgraph deploy 或 Docker |
| 监控 |
无 |
LangSmith 集成 |
12.3 实战
实战 1:langgraph.json 项目配置
{
"graphs": {
"agent": "./agent.py:graph"
},
"store": {
"index": {
"embed": "openai:text-embeddings-3-small",
"dims": 1536,
"fields": ["$"]
}
},
"env": {
"OPENAI_API_KEY": "your-api-key"
}
}
实战 2:Postgres 持久化配置
import os
from langgraph.checkpoint.postgres import PostgresSaver
from langgraph.store.postgres import PostgresStore
import psycopg2
# 连接数据库
conn = psycopg2.connect(os.environ["DATABASE_URL"])
# 配置 Checkpointer
checkpointer = PostgresSaver(conn)
checkpointer.setup() # 创建表和索引
# 配置 Store
store = PostgresStore(conn)
store.setup()
# 编译图
graph = builder.compile(
checkpointer=checkpointer,
store=store,
)
实战 3:SDK 远程调用
from langgraph_sdk import get_client
# 连接到 LangGraph Server
client = get_client(url="http://localhost:2024")
# 流式调用
async for chunk in client.runs.stream(
None, # thread_id(None = 无状态)
"agent", # assistant_id(对应 langgraph.json 中的 graphs key)
input={
"messages": [{"role": "human", "content": "你好,帮我查询订单"}]
},
):
print(chunk.event, chunk.data)
实战 4:错误重试策略
from langgraph.types import RetryPolicy
# 在 add_node 时配置重试
builder.add_node(
"api_call",
api_node,
retry_policy=RetryPolicy(
max_attempts=3, # 最多重试 3 次
initial_interval=1.0, # 首次重试等待 1 秒
backoff_factor=2, # 指数退避因子(1s → 2s → 4s)
retry_on=Exception, # 重试的错误类型
),
)
12.4 API 速查
| API |
完整签名 |
入参说明 |
返回值 |
说明 |
langgraph dev |
CLI 命令 |
无 |
开发服务器 |
启动本地开发服务器 |
langgraph deploy |
CLI 命令 |
无 |
部署 |
部署到 LangSmith Cloud |
get_client(url) |
get_client(url: str) |
url: 服务地址 |
Client |
SDK 客户端 |
RetryPolicy(max_attempts, ...) |
RetryPolicy(max_attempts, initial_interval, backoff_factor) |
max_attempts: 最大重试次数; initial_interval: 初始等待秒数; backoff_factor: 退避因子 |
RetryPolicy |
节点重试策略 |
PostgresSaver(conn).setup() |
.setup() |
无 |
无 |
初始化数据库表结构 |
12.5 错误与避坑指南
坑 1:生产环境用 MemorySaver
# ❌ 生产环境错误写法
checkpointer = MemorySaver() # 服务重启后所有对话状态丢失!
# ✅ 生产环境正确写法
from langgraph.checkpoint.postgres import PostgresSaver
checkpointer = PostgresSaver(conn)
checkpointer.setup()
坑 2:未设置数据库连接池
# ❌ 错误:单连接,高并发时瓶颈
conn = psycopg2.connect(DATABASE_URL)
checkpointer = PostgresSaver(conn)
# ✅ 正确:使用连接池
from psycopg2.pool import ThreadedConnectionPool
pool = ThreadedConnectionPool(minconn=5, maxconn=20, dsn=DATABASE_URL)
checkpointer = PostgresSaver(pool)
坑 3:忽略工具调用超时
# ❌ 错误:工具调用可能无限等待
@tool
def external_api(query: str) -> str:
response = requests.get(...) # 没有超时设置
return response.text
# ✅ 正确:设置超时 + 重试
@tool
def external_api(query: str) -> str:
try:
response = requests.get(..., timeout=10)
return response.text
except requests.Timeout:
return "服务暂时不可用,请稍后重试"
12.6 最佳实践总结
- 开发用
langgraph dev,生产用 langgraph deploy 或 Docker:环境统一
- 使用 PostgresSaver + PostgresStore 持久化:高可用、支持并发
- 关键节点设置 RetryPolicy:自动重试 + 指数退避
- 集成 LangSmith 监控:追踪每次 LLM 调用和图执行
- 工具调用设置超时:防止外部服务拖垮整个 Agent
附录 A:完整 API 速查手册
A.1 图构建 API
| API |
导入路径 |
签名 |
说明 |
StateGraph |
langgraph.graph |
StateGraph(state_schema) |
创建状态图构建器 |
add_node |
StateGraph 方法 |
.add_node(name, action) |
注册节点 |
add_edge |
StateGraph 方法 |
.add_edge(start, end) |
添加普通边 |
add_conditional_edges |
StateGraph 方法 |
.add_conditional_edges(source, path, path_map) |
添加条件边 |
add_sequence |
StateGraph 方法 |
.add_sequence(nodes) |
批量添加顺序节点 |
compile |
StateGraph 方法 |
.compile(checkpointer, store, ...) |
编译为可执行图 |
START |
langgraph.graph |
常量 "__start__" |
图入口 |
END |
langgraph.graph |
常量 "__end__" |
图出口 |
A.2 State 与 Reducer API
| API |
导入路径 |
说明 |
TypedDict |
typing |
定义 State 的推荐方式 |
Annotated |
typing_extensions |
声明字段的 Reducer |
add_messages |
langgraph.graph |
消息专用 Reducer |
operator.add |
operator |
数值/列表累加 Reducer |
MessagesState |
langgraph.graph |
预构建的 messages State |
A.3 消息 API
| API |
导入路径 |
说明 |
HumanMessage |
langchain_core.messages |
用户消息 |
AIMessage |
langchain_core.messages |
AI 回复 |
ToolMessage |
langchain_core.messages |
工具执行结果 |
SystemMessage |
langchain_core.messages |
系统提示词 |
A.4 工具 API
| API |
导入路径 |
说明 |
@tool |
langchain_core.tools |
将函数标记为工具 |
ToolNode |
langgraph.prebuilt |
自动处理工具调用 |
tools_condition |
langgraph.prebuilt |
判断是否有 tool_calls |
create_react_agent |
langgraph.prebuilt |
预构建 Agent |
A.5 持久化 API
| API |
导入路径 |
说明 |
MemorySaver |
langgraph.checkpoint.memory |
内存 Checkpointer |
SqliteSaver |
langgraph.checkpoint.sqlite |
SQLite Checkpointer |
PostgresSaver |
langgraph.checkpoint.postgres |
Postgres Checkpointer |
InMemoryStore |
langgraph.store.memory |
内存 Store |
PostgresStore |
langgraph.store.postgres |
Postgres Store |
A.6 流程控制 API
| API |
导入路径 |
说明 |
interrupt |
langgraph.types |
暂停执行 |
Command |
langgraph.types |
动态控制流程 |
Send |
langgraph.types |
并行分发 |
RetryPolicy |
langgraph.types |
重试策略 |
Runtime |
langgraph.runtime |
运行时上下文 |
A.7 流式输出 API
| API |
导入路径 |
说明 |
.stream() |
CompiledGraph 方法 |
同步流式 |
.astream() |
CompiledGraph 方法 |
异步流式 |
.stream_events() |
CompiledGraph 方法 |
v3 事件流式 |
get_stream_writer |
langgraph.config |
自定义流式事件 |
|
|
|