← 返回列表

阅读 —下载 —

MCP Server 多实例与负载均衡问题

一、是什么问题?

1. 传统业务系统是怎么解决高并发的?

在传统后端系统中,一个业务服务通常不会只部署一个实例,而是部署多个实例。

例如公司的订单服务:

                         Business Gateway
                               │
                  ┌────────────┼────────────┐
                  ↓            ↓            ↓
              Order-01     Order-02     Order-03
                  │            │            │
                  └────────────┼────────────┘
                               ↓
                             MySQL

用户请求:

GET /api/order/12345

先经过 Business Gateway,由 Gateway 把请求分发到不同的 Order Service 实例。

这样可以实现:

  • 多实例横向扩容
  • 请求负载均衡
  • 单实例故障摘除
  • 提升系统并发能力

2. MCP 场景产生了什么问题?

现在我们把订单查询能力通过 MCP 暴露给 Agent。

用户在飞书中说:

“帮我查询一下订单 12345 的状态。”

Agent 决定调用:

query_order(order_id=12345)

请求不再直接调用传统 HTTP API,而是:

Agent
  ↓
MCP Server
  ↓
Order API

这时候就出现一个问题:

MCP Server 自己是不是也需要像传统业务服务一样部署多个实例?如果部署多个实例,Agent 的 MCP 请求能不能自动负载均衡?

答案是:

可以。MCP Server 完全可以多实例部署。

但 MCP 场景相比普通 HTTP API,需要额外考虑:

MCP 可能存在 Session、连接、Streaming 以及实例本地状态。

这就是 MCP 多实例部署时真正需要解决的问题。


二、为什么 MCP 会出现这个问题?

核心原因是:

传统业务 API 通常强调无状态请求,而 MCP 除了 Tool 调用之外,还可能涉及 Session、持续连接和执行上下文。

下面还是用“查询订单”这个例子。


1. 普通业务 API 很容易做多实例

比如:

用户
 ↓
Business Gateway
 ↓
┌──────────┬──────────┬──────────┐
↓          ↓          ↓
Order-01  Order-02  Order-03

假设:

请求 A → Order-01
请求 B → Order-02
请求 C → Order-03

只要订单数据存在 MySQL 中,三个实例都能处理。

因为:

Order-01 ─┐
Order-02 ─┼──→ MySQL
Order-03 ─┘

业务状态没有放在某一个实例的内存里。

所以它天然适合负载均衡。


2. MCP 可能存在 Session

MCP Client 和 MCP Server 建立连接之后,可能存在一个 Session:

Agent
  │
  │ Session A
  ↓
MCP Server-01

假设 Session A 的相关状态只保存在:

MCP Server-01
└── Session A

那么下一次请求经过 Gateway,被分到了:

Agent
  ↓
MCP Gateway
  ↓
MCP Server-02

但是:

MCP Server-02
└── 没有 Session A

这时候就可能出现 Session 不一致的问题。


3. MCP 还可能存在 Streaming / 长连接

例如 Agent 调用一个耗时较长的 Tool:

Agent
  ↓
MCP Server
  ↓
Tool
  ↓
业务系统

执行过程中可能存在持续的数据传输。

它和普通的:

POST /api/order

这种“一次请求 → 一次响应”的模式不完全一样。

因此 MCP 多实例部署时,需要考虑:

  • Session 应该保存在哪里?
  • 长连接应该如何管理?
  • 请求能不能随意切换实例?
  • 实例故障之后 Session 怎么恢复?
  • Tool 执行状态是否依赖某一个实例?

4. 用订单查询例子总结

原来的业务系统:

用户
 ↓
Business Gateway
 ↓
Order-01 / Order-02 / Order-03

问题比较简单:

请求打到哪个 Order Service 都可以。

而 MCP:

Agent
 ↓
MCP Gateway
 ↓
MCP-01 / MCP-02 / MCP-03

如果:

Session A
    ↓
MCP-01

下一次:

Session A
    ↓
MCP-02

但 Session A 只存在 MCP-01:

MCP-01
└── Session A

MCP-02
└── 没有 Session A

那么多实例负载均衡就不能简单地理解成:

“请求随机扔给任意一个 MCP Server 就行。”

这就是 MCP 多实例场景真正需要解决的问题。


三、怎么解决?

核心思路就三个:

MCP Server 多实例化 + 共享状态外置 + Gateway 负责负载均衡。

还是使用刚才的“查询订单”例子。


1. 第一层:MCP Server 多实例 + MCP Gateway

我们把 MCP Server 部署成多个实例:

                         Agent
                           │
                           ↓
                     MCP Gateway
                           │
              ┌────────────┼────────────┐
              ↓            ↓            ↓
           MCP-01       MCP-02       MCP-03

用户查询:

“帮我查询订单 12345”

Agent 调用:

query_order(12345)

MCP Gateway 根据负载把请求分给:

MCP-02

于是:

Agent
 ↓
MCP Gateway
 ↓
MCP-02

如果现在有 10,000 个 Agent 请求,就可以部署更多实例:

MCP-01
MCP-02
MCP-03
...
MCP-20

由 MCP Gateway 把请求分摊到这些实例。

这一层解决的是:

MCP 能力层自身的高并发和横向扩展问题。


2. 第二步:把 Session / 共享状态外置

为了避免:

MCP-01
└── Session A

MCP-02
└── 不认识 Session A

不要把关键 Session 状态只放在某一个 MCP Server 的本地内存里。

而是:

                 ┌── MCP-01
                 │
MCP Gateway ─────┼── MCP-02
                 │
                 └── MCP-03
                       │
                       ↓
                 Redis / DB

例如:

Redis

Session A
├── userId
├── tenantId
├── permission
└── execution context

那么:

第一次:

Agent
 ↓
MCP Gateway
 ↓
MCP-01
 ↓
Redis

下一次:

Agent
 ↓
MCP Gateway
 ↓
MCP-02
 ↓
Redis

MCP-02 依然可以拿到 Session A 的状态。

因此:

MCP Server 尽可能无状态,共享状态放到 Redis / DB 等外部存储。


3. 第三步:MCP Server 再调用原来的业务系统

注意:

MCP Server 不需要替代原来的业务服务。

还是刚才的订单查询。

MCP Server 收到:

query_order(12345)

然后转换成传统业务 API:

GET /api/order/12345

再进入原来的 Business Gateway:

Agent
 ↓
MCP Gateway
 ↓
MCP-02
 ↓
Business Gateway
 ↓
┌──────────┬──────────┬──────────┐
↓          ↓          ↓
Order-01  Order-02  Order-03
 ↓          ↓          ↓
        MySQL

假设这一次 Business Gateway 把请求分给:

Order-03

那么完整链路就是:

Agent
  │
  │ query_order(12345)
  ↓
MCP Gateway
  │
  ↓
MCP-02
  │
  │ GET /api/order/12345
  ↓
Business Gateway
  │
  ↓
Order-03
  │
  ↓
MySQL

这里就出现了两层独立的负载均衡:

第一层

MCP Gateway
      ↓
MCP Server × N

解决:

MCP 能力层的高并发。

第二层

Business Gateway
      ↓
Business Service × N

解决:

传统业务系统的高并发。

两层不是 MCP 特有的机制,而是因为:

MCP 能力层和传统业务服务本来就是两个独立的服务集群。


4. 最终推荐架构

对于企业级 MCP 平台,可以最终设计成:

                         User
                           │
                           ↓
                         Agent
                           │
                           ↓
                    ┌──────────────┐
                    │ MCP Gateway  │
                    │ LB/Auth/Rate │
                    └──────┬───────┘
                           │
             ┌─────────────┼─────────────┐
             ↓             ↓             ↓
          MCP-01        MCP-02        MCP-03
             │             │             │
             └─────────────┼─────────────┘
                           │
                     Redis / DB
                  Session / State
                           │
                           ↓
                     Tool Runtime
                           │
                           ↓
                  Business Gateway
                           │
             ┌─────────────┼─────────────┐
             ↓             ↓             ↓
         Order-01      Order-02      Order-03
             │             │             │
             └─────────────┼─────────────┘
                           ↓
                         MySQL

最核心的设计原则

MCP Server
    ↓
尽量无状态
    ↓
Session / 共享状态外置
    ↓
Gateway 负责负载均衡
    ↓
MCP Server 横向扩容
    ↓
继续调用原有业务 Gateway
    ↓
业务服务继续多实例部署

因此最终可以用一句话回答这个问题:

MCP Server 可以像普通后端服务一样做多实例和负载均衡,MCP 本身不负责负载均衡。MCP 真正需要额外解决的是 Session、Streaming 和实例状态问题,所以生产环境通常让 MCP Server 尽量无状态,把共享状态外置到 Redis/DB,通过 MCP Gateway 做第一层负载均衡;MCP Server 再调用原有 Business Gateway,由业务服务集群承担第二层业务并发。