随着生成式 AI 的普及,企业内部的 AI 系统正从“单点应用”向“集群化”演进。当我们需要管理数十个业务 Agent 和成百上千个功能接口时,传统的代码耦合方式将成为瓶颈。本文将探讨如何利用 MCP (Model Context Protocol) 协议,构建一套标准化、高可观测且安全隔离的 Agent 集群架构。

为什么需要 MCP 集群架构?

在 Agent 集群初期,每个 Agent 往往各自维护工具集、提示词和资源。当系统规模扩大至 10+ 业务系统和 80+ 工具服务时,这种“烟囱式”架构会带来巨大的维护成本。

1. 核心痛点与解决思路

  • 路由与调度 (The Router Layer)

    • 通俗理解:大模型的上下文窗口就像考场上有限的桌面面积,你不可能把 100 本参考书全摊在桌上。你需要一个“图书管理员”,根据当前考题动态递给你最相关的 3 本书。

    • 核心实现:引入 Agent Router。在实际开发中,我们通常会让网关层大模型先做一次轻量级的“意图识别”,然后再将对应的 MCP Server 注入到业务 Agent 中。

伪代码示例

async def route_mcp_servers(user_query: str):
    # 1. 轻量级模型进行意图分类
    intent = await llm.classify(user_query, categories=["draw", "search", "database"])

    # 2. 根据意图动态挂载 MCP Server
    active_servers = []
    if intent == "draw":
        active_servers.append(registry.get("image-mcp"))
    elif intent == "database":
        active_servers.append(registry.get("sql-mcp"))

    return active_servers
 

  • 统一记忆体 (Global Memory)

    • 通俗理解:如果客服 Agent 知道用户对花生过敏,但推荐 Agent 不知道,用户就会感到系统十分“弱智”。记忆体就像是一个全公司共享的VIP档案室

    • 核心实现:构建独立的用户画像 MCP。在数据库层面,我们使用 PostgreSQL 的 UPSERT 特性来实现高并发下的幂等写入,确保跨项目的数据同步不会产生脏数据。

SQL 示例 (ON CONFLICT DO UPDATE)

INSERT INTO user_profiles (user_id, allergies, preference)
VALUES ('u1001', '花生', '极简风格')
ON CONFLICT (user_id) 
DO UPDATE SET 
    allergies = EXCLUDED.allergies,
    preference = EXCLUDED.preference,
    updated_at = NOW();
 

  • 链路追踪 (Observability)

    • 痛点:当一通 AI 语音电话延迟了 3 秒,你无法判断是网关卡住了,还是外部大模型 API 变慢了。通过注入全局的 trace_id,我们可以清晰地观测整个调用链路。

架构核心设计:REST 与 MCP 的协议桥接

为了让现有 Web 系统无感接入 AI,我们基于 FastAPI 设计了 REST → MCP 协议桥接网关

1. 四层中间件设计

网关的核心是请求拦截与处理。我们通过 FastAPI 的中间件链(Middleware)来实现认证、日志、配额管控与全链路追踪。

代码:网关中间件的核心逻辑

from fastapi import Request
import uuid
import time

@app.middleware("http")
async def gateway_core_middleware(request: Request, call_next):
    # 1. 生成全局 Trace ID
    trace_id = request.headers.get("X-Trace-Id", str(uuid.uuid4()))
    
    # 2. 鉴权与配额检查 (AuthZ & Quota)
    api_key = request.headers.get("Authorization")
    project_id = await verify_and_get_project(api_key)
    if not await check_quota_limit(project_id):
        return JSONResponse({"error": "Quota Exceeded"}, status_code=429)

    # 3. 记录请求开始时间,将 trace_id 注入上下文
    start_time = time.time()
    request.state.trace_id = trace_id
    
    # 4. 执行路由与实际业务
    response = await call_next(request)
    
    # 5. 耗时埋点与日志对齐
    process_time = time.time() - start_time
    logger.info(f"[Trace: {trace_id}] Project: {project_id} | Path: {request.url.path} | Time: {process_time:.3f}s")
    
    response.headers["X-Trace-Id"] = trace_id
    return response

2. 通信机制:Streamable HTTP

MCP 需要 Client 和 Server 频繁进行意图确认(“你有加法工具吗?” -> “有” -> “帮我算 1+1”)。相比于单向推送的 SSE,基于 Streamable HTTP 的长连接机制就像是对讲机,握手一次即可保持双向通道,极大降低了重复建立连接的延迟。

为什么选择 Streamable HTTP?

在通信机制上,我们放弃了传统的单次 HTTP 请求和 SSE,选择了 Streamable HTTP。

  • SSE(单向大喇叭):像看电视直播,服务器一直播报,你只能听,不能插嘴。

  • Streamable HTTP(双向对讲机):像打微信电话。MCP 需要 Client 和 Server 频繁进行意图确认(“你有加法工具吗?” -> “有” -> “那帮我算 1+1”)。Streamable HTTP 握手一次即可保持长连接通道,极大降低了重复建立连接的延迟。

代码示例:基于 Streamable HTTP 的 MCP Client 极简实现 在实际业务中,网关层通过以下方式与 MCP Server 建立持久连接,并连续调用多个工具:

import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

async def main():
    # 这里的 URL 通常由网关 Router 动态分配
    url = "http://127.0.0.1:9000/mcp"
    print(f"正在连接 MCP Server: {url}")

    # 1. 修筑一条“双向高速通道”
    async with streamablehttp_client(url) as (read, write, _):
        # 2. 建立长连接会话
        async with ClientSession(read, write) as session:
            await session.initialize()
            print("握手成功,通道已建立!\n")

            # 3. 获取并调用工具 (无需反复断开和重连)
            tools = await session.list_tools()
            print(f"当前节点可用工具 ({len(tools.tools)} 个)")

            # 连续执行多个任务
            await session.call_tool("hello", {"name": "MCP Client"})
            await session.call_tool("add_record", {"uid": 1001, "action": "login"})

Agent 集群部署流水线

高质量的集群部署依赖于云原生的底座。我们完全抛弃了传统的手动部署,全面拥抱 Serverless 与 CI/CD 自动化。

1. 自动化构建与推流

我们在 GitLab CI/CD 的 Shell 脚本中,自动化了镜像打包与推流的过程。为了不影响本地开发,我们通常会区分不同环境的 Dockerfile。

代码示例:触发构建与上传阿里云镜像仓库

# 1. 登录云端容器镜像服务
docker login --username=$ALIYUN_USER $REGISTRY_URL -p $ALIYUN_PWD

# 2. 使用专用的 Dockerfile.aliyun 构建多架构镜像
echo "开始构建 MCP Backend 镜像..."
docker build -f Dockerfile.aliyun --platform linux/amd64 \
  -t $REGISTRY_URL/my-namespace/agent-backend:v1.0.0 .

# 3. 推送镜像至云端
docker push $REGISTRY_URL/my-namespace/agent-backend:v1.0.0
echo "部署包上传完成,触发 Serverless 平台拉取更新..."

2. 负载均衡与安全管控

部署到 Serverless (如 SAE / 云函数) 后,我们需要在网络层把守大门:

  • 反向代理(CLB/Nginx - 接线员):负责把海量外部请求分配给最空闲的后端容器,自动剔除处于“不健康”状态的实例,并统一处理 HTTPS 证书卸载。

  • NAT 网关(安全传达室)

    • SNAT(代拨电话):让内网的 Agent 服务器能安全地访问外部的 OpenAI/豆包 API,同时隐藏物理 IP。

    • DNAT(分机转发):将公网特定端口的安全请求,精准映射到内网某个 MCP 服务的监听端口上。

3. 高可用策略

  • 优雅降级:当“高级深度检索引擎”超时,Agent 不应直接抛出 500 Error,而是自动切换至简易版模型或返回预设的兜底话术(如:“资料库正在维护,请稍后再试”)。

  • 令牌桶限流:通过配额管控,防止某个“实验性质的侧边栏小助手”因为 Bug 死循环,把公司主账号的大模型 API 额度瞬间刷爆。

总结

在落地 Agent 集群时,我们总结了以下核心法则:

1. Prompt 的解耦与外置管理

千万不要把提示词写死在代码的字符串里!我们通过 YAML 将 Prompt 独立为资产,服务端渲染后返回。 代码示例:YAML 格式的 Prompt 模板

YAML

name: "CustomerService"
version: "v2.0"
parameters:
  - user_name
  - user_portrait  # 动态注入的用户画像
template: |
  你是金牌客服。你正在接待 {user_name}。
  根据记忆中心的数据,该用户具有以下特征:{user_portrait}
  请根据用户的性格特征,使用恰当的语气进行回复。

好处:运营人员调整话术时,无需研发重新打包发布代码,热更新即时生效。

2. Agent 编排七步法

我们将复杂的 Agent 运行逻辑拆解为一条标准的流水线,就像米其林餐厅的后厨标准化作业

  1. 召回历史 (看老顾客以前点过啥)

  2. 读取画像 (确认顾客有没有忌口)

  3. 检索知识 (翻看最新的菜谱)

  4. 渲染 Prompt (写一张包含所有要求的备菜条)

  5. LLM 推理 (主厨开始做菜)

  6. 保存记忆 (把今天的点单记录存进系统)

  7. 提取事实 (备注:这名顾客今天觉得口味偏淡,以后多加盐)

通过这套流水线,Agent 本身不再持有复杂状态,而是变成了“无状态”的计算单元,所有状态都下沉到 MCP 共享服务中,极大地提升了系统的可扩展性。

3. 人工介入的底线

记住:模型训练即封印。AI 编程确实能解决 99% 的问题,但对于向量嵌入(Embedding)等核心逻辑,如果前置给到 AI 的文档语义切分就是错的,模型必然产生幻觉。那最后的 1%,始终需要人工进行数据清洗与架构纠偏。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐