MCP 实战手记(十三):MCP多租户隔离,一个网关服务多个团队

发布时间:2026/10/30 15:41:44
MCP 实战手记(十三):MCP多租户隔离,一个网关服务多个团队 前置篇六自建 MCP 网关、篇八无状态生产落地、篇九6层安全防护技术基线MCP Java SDK 2.0.0非 Spring AI同篇六网关多租户在传输拦截器层实施不依赖 Spring AI 注解实测环境本地 Docker 内置 k8s双网关实例 Redis本文实测项均在该环境验证引子网关接了第三个团队开始串味篇六我把网关搭起来了门店运营的工具先挂上去跑得挺好。后来供应链团队说我们也想用再后来财务团队也来了。第三个团队接进来那天出了两件事财务的gen_finance_report被供应链误调——不是故意是工具目录没隔开搜出来就点了供应链写了个脚本狂刷get_inventory把门店那边的配额全吃光门店大促时调不动。这一刻我懂了一个网关服务多团队不隔离就是事故。本文就讲怎么在已有网关上把多租户这层补上——租户路由、凭证隔离、配额、数据隔离四件套。范围说明本文是逻辑隔离单网关按 tenantId 过滤实例级强隔离只在对比里提不展开部署。预算计量、错误处理属于另一回事见配套散点文。一、为什么需要多租户动机说明成本一套网关养多个团队远比每团队各起一套省运维隔离工具、权限、数据、配额都按租户隔开互不串味合规财务/HR 这类敏感租户出了泄漏能定位到哪个租户不隔离的三类后果正是引子里的真实事故串调工具可见性、超额配额、泄漏数据。下面四个小节一一对应解决。二、三种多租户方案对比方案做法隔离强度成本适用共享实例逻辑隔离单网关一切按tenantId过滤中同进程最低本文做法绝大多数企业够用实例级隔离每租户独立网关实例 / 命名空间高进程级高强合规金融/政务混合核心租户独立实例 长尾共享高中多数中大型企业选共享实例逻辑隔离因为它改动最小、复用篇六网关、且配额/凭证天然能集中。实例级隔离只是把逻辑换成物理过滤逻辑一样本文不重复。三、租户路由请求怎么认出是哪个租户传递方式三选一推荐第三种API Key 隐含 tenantIdKey 查表得租户——简单但 Key 轮换时要同步映射独立头X-Tenant-Id——直观但客户端要配合带Token claim 带 tenantOAuth 2.1 / IdP 签发时塞tenantclaim——最干净与篇九 L2/L3 身份体系打通。本文用方案 12 组合演示Key 映射为主X-Tenant-Id为辅覆盖服务间调用生产建议升级到方案 3。在传输层提取 tenantId实测落地版代码见13-multitenant/TenantFilter.java// 传输层拦截每个请求先解析租户缺失/非法直接拒再做配额计数ComponentpublicclassTenantFilterextendsOncePerRequestFilter{privatefinalTenantStorestore;privatefinalQuotaServicequota;OverrideprotectedvoiddoFilterInternal(HttpServletRequestrequest,HttpServletResponseresponse,FilterChainchain)throwsServletException,IOException{StringapiKeyfirstNonBlank(request.getHeader(X-Api-Key),request.getHeader(X-Tenant-Id));TenantProperties.TenantDeftenantstore.resolve(apiKey);// Redis 查映射if(tenantnull){reject(response,401,unknown tenant);return;}if(POST.equalsIgnoreCase(request.getMethod())!quota.allow(tenant)){reject(response,429,tenant quota exceeded);return;}MDC.put(tenant,tenant.getId());// 日志全链路带租户TenantContext.set(tenant.getId());// 下游拦截器/工具可取try{chain.doFilter(request,response);}finally{TenantContext.clear();MDC.remove(tenant);}}}✅已实测核对结论与初稿假设不同MCP Java SDK 2.0.0不提供ServerTransportInterceptor接口——篇六网关实际用的是HttpServletStatelessServerTransportMcpServer.sync(...)SDK 暴露的是 transport provider不是拦截器。因此按预案把拦截等价迁移到 Servlet Filter位置同样在传输层逻辑完全一致解析租户 → 拒非法 → 配额 → 写上下文/日志。若后续 SDK 提供装饰器式扩展点把这四步搬过去即可业务代码零改动。四、凭证隔离不同租户不同 API Key每个租户签发独立 KeyKey→tenantId 映射存 Redistenant:key:{hash}→ tenantId。吊销/轮换删 Redis 键即生效无需重启网关——这是 Redis 集中存的好处。与篇九L2 客户端身份衔接本文的 Key 是客户端身份那一层租户内的用户身份走篇九 L3X-User-Id / ID-JAG。// 凭证签发与校验示意Stringkeysk-TenantId-random32();redis.opsForValue().set(tenant:key:hash(key),tenantId,Duration.ofDays(90));// 90天过期// 校验拦截器里 resolve(apiKey) 命中即过未命中 401五、配额管理别让一个租户刷爆这是引子里供应链刷爆门店配额的直接解。计数放 Redis天然跨实例一致——呼应篇八“多实例下状态要外置”配额计数属于下一次请求打到另一个实例还必须对的数据所以必须进 Redis。固定窗口配额Redis Lua 原子自增 TTL非真滑动窗口// 固定窗口窗口60s TTL首调用起算每次自增会续期 TTL故是固定窗口而非真滑动窗口// 真滑动窗口需用 ZSET 记每次时间戳本文为可读性用固定窗口近似生产可按精度升级Stringlua local cnt redis.call(INCR, KEYS[1]) if cnt 1 then redis.call(EXPIRE, KEYS[1], 60) end return cnt ;Longnowredis.eval(lua,List.of(quota:tenantId:toolName),List.of());if(nowlimit)thrownewQuotaExceededException(429,tenant quota exceeded);超限返回429与篇九L5 限流一致limit按租户配置长尾租户低配、核心租户高配。多实例一致性因为计数在 Redis两个网关副本Docker/k8s 双实例看到的是同一份数字——不会出现副本A 限了、副本B 还放的裂隙。这恰好是篇八会话数据外置思想在配额上的落地。✅已实测双副本 Redis起两个网关副本18080/18081本机 8080 被占故改用高位端口 共享 Redis从副本A 连续打满门店租户配额limit20 / 窗口60s副本B 立即同样 429——实测输出GW1 hit 1~20 - 200 GW1 hit 21~23 - 429 GW2 store - 429 # 同一租户计数在 Redis换副本同样被限 GW2 supply - 200 # 未超限租户不受影响证明是租户级而非全局限流故障演练Redis 挂了怎么办两种策略——fail-open放行保可用适合内部可信或fail-closed全拒保隔离适合多租户公网。本文选按租户分级核心租户 fail-closed长尾租户 fail-open。配置示例# 配额降级策略按租户分级 quota.failover.policy.coreclosed # 核心租户Redis 不可用时全拒保隔离 quota.failover.policy.longtailopen # 长尾租户Redis 不可用时放行保可用六、数据隔离日志 / 配置 / 缓存类型做法日志MDC 带tenant按租户分索引敏感租户财务/HR行级脱敏后再落盘配置租户级配置命名空间cfg:{tenantId}:...避免共享 map 串改缓存所有缓存 key 前缀tenant:{id}:即使同 key 不同租户也不串与篇八会话数据外置 Redis同一套键规范redis.opsForValue().set(tenant:tenantId:ctx:sessionKey,ctx,Duration.ofMinutes(30));七、实战在现有网关上加多租户拓扑本地 Docker 内置 k8s 验证环境┌──────────── LB / Ingress ────────────┐ │ │ client ──┤ gw-1 (MCP 网关副本1) ┐ │ │ gw-2 (MCP 网关副本2) ├─ 共享 ── Redis租户映射 配额计数│ │ (k8s Deployment 2副本)┘ │ └───────────────────────────────────────┘两个网关副本无状态篇八状态全在 Redis扩副本只改replicas隔离逻辑不变。改造步骤清单引入TenantTransportInterceptor所有请求先解析租户接 Redis 存 Key→tenant 映射与配额计数工具目录按租户过滤租户只能 list 到自己被授权的工具——防引子的误调MDC 缓存 key 前缀接入双副本部署跑配额一致性 故障演练。目录过滤是关键引子事故①财务工具被供应链误调的根因是目录没隔开。租户 list 工具时网关只返回该租户allowed_tools集合内的工具——看不见就点不到。✅已实测以上拓扑与演练已跑通真实输出如下本机双副本 Redis 容器。 1) 租户路由 no-key - 401 bad-key - 401 store - 200 2) 目录隔离看不见就点不到 store 目录: {tools:[get_store_sales,get_inventory],tenant:store} finance 目录: {tools:[gen_finance_report],tenant:finance} PASS: 门店目录已过滤不含 gen_finance_report 3) 凭证隔离 supply - get_store_sales - 403 5) 故障演练Redis 不可用按租户分级 finance(closed) - 429 # 核心租户全拒保隔离 supply(open) - 200 # 长尾租户放行保可用 恢复 Redis 后 - 200 # 自愈无需重启八、诚实边界mTLS 未实测租户间传输加密依赖篇九L1本文不重复本机未跑真实证书体系。实例级隔离未展开仅对比提及强合规场景的部署成本需另文。真实压测待补双副本下的配额吞吐基线P95待压测填充避免拍脑袋给数字。SDK API 已核对MCP Java SDK 2.0.0 无ServerTransportInterceptor接口第三节已按预案改为 Servlet Filter 落地并实测跑通结论见该节。预算计量不在此篇按租户成本归因见配套散点文三大坑·坑二。九、与全季的关系 多租户自查清单互链点击跳转对应篇章→ 篇六自建 MCP 网关本文在其基础上加租户层不重造网关。→ 篇八无状态生产落地双副本无状态 状态外置 Redis思路同源。→ 篇九6层安全防护Key 是 L2 客户端身份租户内用户身份走 L3。→ 散点文《企业级 MCP 部署三大坑》待发布预算坑二、错误码坑三、Schema 版本隐藏坑是本文未覆盖的企业部署另一半。多租户自查清单项必做请求能可靠解析 tenantId缺失/非法即拒必做每租户独立凭证可独立吊销必做工具目录按租户过滤看不见点不到必做配额计数跨实例一致Redis 集中必做超限返回 429 降级策略fail-open/closed 分级必做日志/缓存按租户隔离、敏感租户脱敏必做双副本 failover 演练过建议一句话收尾多租户不是再起一套而是在同一套网关上把 tenantId 当成第一公民——路由认租户、凭证分租户、配额限租户、数据隔租户。四件套做完一个网关就能安稳服务好几个团队。代码已开源本篇四件套实现见13-multitenant/模块Spring Boot 4.0.0 Java 21 Redistagv13—— Gitee / GitHub。mvn clean package后docker compose up -d起双副本./verify-multitenant.sh一键复现上文全部实测输出觉得有用欢迎 star。相关阅读第二季 · 企业级 MCP 生产落地篇六自建 MCP 网关本文多租户层直接搭在它上面篇八无状态MCP Server生产落地清单双副本无状态 状态外置 Redis思路同源篇九生产化MCP Server的6层安全防护Key 是 L2 客户端身份租户内用户身份走 L3篇十二企业级Toolbox治理同季前作工具治理与多租户是企业落地的两块拼图本篇 tenantId 字段即由它定义

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询