MCP Gateway 实战
核心结论
企业有几百个存量接口,想让 AI Agent 调用它们,传统做法是每个接口写一个 @Tool 方法——100 个接口 = 100 个方法 = 改代码 + 重新部署,运维和开发强耦合,效率极低。MCP Gateway 的核心思想:配置即工具,JSON/YAML 配置一写,运行时动态生成 ToolCallback,零代码接入,配置变更秒级生效,这才是生产环境该有的样子。
- 🔥 MCP 是 2025 年 AI 工具生态最重要的协议标准,各大厂都在跟进,越早掌握越有优势
- 💰 动态 ToolCallback + 策略模式 + 事件驱动 + 双层缓存,架构设计面试直接起飞
- 🎯 自研 Netty RPC 框架,覆盖粘包拆包、异步转同步、连接池、主从 Reactor 等全部高频面试考点
- 🚀 不是简单的代理转发,而是生产级的 AI 基础设施,5 大设计模式教科书级落地
- ⚡ 新增协议只需实现一个接口,零改动路由代码——开闭原则的完美体现
项目架构

痛点与方案
传统做法的三大致命问题:
- 每新增一个接口,都要改代码、重新部署——100 个接口改 100 次
- 接口参数变了,又要改代码——运维被开发绑架
- 运维和开发强耦合,效率极低——AI 落地被卡在"接口接入"这一步
MCP Gateway 一招解决:
- 把"接口→工具"的映射关系抽象成 JSON/YAML 配置
- 运行时动态生成
FunctionToolCallback,无需编译 - 配置变更 → 事件发布 → 缓存自动刷新,秒级生效,无需重启
七大核心亮点,面试直接起飞
亮点一:动态 ToolCallback 生成——整个 Gateway 的灵魂
把 JSON 配置转换成 Spring AI 的 ToolCallback,这是整个项目最核心的设计:
AtomicReference<ToolCallback[]>保证并发读写安全,高并发场景下不会出问题@EventListener监听配置变更,自动刷新缓存,运维改个配置就生效FunctionToolCallback.builder动态构建,无需编译时确定,真正的"配置即工具"
亮点二:协议适配器路由——策略模式教科书实现
通过 ProtocolAdapter 接口 + Spring 自动注入所有实现,实现多协议完美解耦:
| 协议 | 适配器 | 状态 |
|---|---|---|
| HTTP | HttpProtocolAdapter | ✅ 已实现(GET/POST/PUT/DELETE) |
| Netty RPC | NettyRpcProtocolAdapter | ✅ 已实现(自研框架) |
| gRPC | - | 🔮 扩展点(实现接口即可) |
| Dubbo | - | 🔮 扩展点(实现接口即可) |
新增协议只需实现 ProtocolAdapter 接口,无需修改一行路由代码——这就是开闭原则的威力。
亮点三:参数映射引擎——四种位置自动处理
支持 PATH / QUERY / HEADER / BODY 四种参数位置自动映射,运维人员配置一下就能用:
endpoint = "http://api.com/orders/{orderId}"
mcpArgs = {"orderId": "12345", "status": "paid"}
结果 = "http://api.com/orders/12345?status=paid"
亮点四:配置注册中心——双层缓存 + 事件驱动
- 双层存储:ConcurrentHashMap 持久化 + Caffeine 缓存加速(最大 15 万条,10 分钟过期)
- 事件驱动:配置变更 → 发布
ConfigChangedEvent→ ToolCallback 缓存自动刷新 - 启动预热:
@PostConstruct全量预热缓存,启动即可用
亮点五:ChatClient 动态注入工具
每次请求时动态注入最新的工具列表,配置变更立即生效,不需要重启应用:
chatClient.prompt()
.user(message)
.toolCallbacks(toolCallbackProvider.getToolCallbacks()) // 每次请求动态注入
.call().content();
亮点六:JSON / YAML 批量导入
支持单条 JSON 注册和 YAML 批量导入,rpc://host:port/service/method 这个 URI 格式让 RPC 配置和 HTTP 配置在管理页面上体验一致——运维人员不需要学习新概念。
亮点七:自研 Netty RPC 框架 🔥🔥🔥
这是本项目最硬核的部分——为什么不用 Dubbo/gRPC?因为用现成框架一行 @DubboReference 就完事了,但你在面试中说不出底层原理。自研 RPC 框架从协议设计到编解码到连接管理,完整覆盖 Netty 面试的所有高频考点:
| 技术点 | 实现方式 | 面试追问 |
|---|---|---|
| 自定义协议 | 魔数 0xCAFE + 版本 + 序列化 + 消息类型 + requestId + 长度 + 数据 | 为什么需要魔数?为什么不直接发 JSON? |
| 粘包拆包 | ByteToMessageDecoder + markReaderIndex/resetReaderIndex | 和 LengthFieldBasedFrameDecoder 的区别? |
| 异步转同步 | CompletableFuture + ConcurrentHashMap<requestId, Future> | 为什么先注册 Future 再发送请求? |
| 多路复用 | 一个 Channel 跑多个请求,靠 requestId 匹配 | 和 HTTP/1.1 Keep-Alive 有什么区别? |
| 连接池 | ConcurrentHashMap<host:port, Channel> + DCL | 连接断了怎么办?(closeFuture 自动清理) |
| 主从 Reactor | bossGroup(1) + workerGroup(CPU×2) | 为什么 boss 只需要 1 个线程? |
| 空闲检测 | IdleStateHandler 60 秒超时踢出 | 和 TCP KeepAlive 的区别? |
| 泛化调用 | Function<Map, String> 替代反射 | 为什么不用反射?性能差多少? |
| 优雅关闭 | @PreDestroy + shutdownGracefully() | shutdownGracefully 做了什么? |
自研 RPC 框架覆盖了 Netty 面试的所有高频考点。别人只会说"用过 Dubbo",你能从魔数校验讲到粘包拆包,从异步转同步讲到连接池 DCL,从主从 Reactor 讲到优雅关闭——这就是降维打击。
5 大设计模式实战落地
| 模式 | 应用场景 | 代码位置 |
|---|---|---|
| 策略模式 | 协议适配器路由,新增协议零改动 | ProtocolAdapterRouter |
| 工厂模式 | 动态生成 ToolCallback,配置即工具 | DynamicToolCallbackProvider.createToolCallback() |
| 观察者模式 | 配置变更事件驱动缓存刷新 | ConfigChangedEvent + @EventListener |
| 模板方法 | HTTP 调用流程标准化 | HttpProtocolAdapter.invoke() |
| 缓存模式 | 双层缓存加速,15 万条配置毫秒级读取 | CachedConfigRegistry |
一个项目同时展示 AI 工程化能力(MCP + 动态工具生成)和底层网络编程能力(Netty RPC),5 大设计模式教科书级落地,面试官看到这个项目就知道你是有真功夫的。