当你真正跨语言测量 MCP 服务器性能时,会发生什么?
当你真正跨语言测量 MCP 服务器性能时,会发生什么?
大多数开发 MCP 服务器的开发者,都是根据使用舒适度来选择编程语言。机器学习领域常用 Python,Web 开发出身的人会选 Node.js,后端工程师则偏向 Java 或 Go。大家普遍认为:协议本身比运行时更重要。
但 TM Dev Lab 的 Thiago Mendes 发布的一项基准测试,狠狠挑战了这一假设。在 390 万次请求、三轮独立测试的结果中,不同语言之间的性能差距大到惊人——不是 2 倍、3 倍的差异,某些场景下甚至达到数量级的差距。
测试环境
研究团队用四种语言实现了 MCP 服务器:
•
Java(Spring Boot + Spring AI)
•
Go(官方 SDK)
•
Node.js
•
Python(FastMCP)
所有服务都容器化,并使用完全相同的资源限制:1 核 CPU、1 GB 内存。
压力测试使用 k6,逐步加压到 50 个并发虚拟用户,持续压测 5 分钟,每轮测试重复三次。
每台服务器都暴露完全相同的四个工具接口:
•
calculate_fibonacci:CPU 密集型递归计算
•
fetch_external_data:I/O 密集型 HTTP 调用
•
process_json_data:JSON 数据转换
•
simulate_db_query:可控延迟模拟(模拟数据库查询)
设计思路是:覆盖不同性能维度,得到全面客观的对比,而不是只挑选对某门语言有利的场景。
架构概览
k6 压力发生器(50 并发用户 · 5 分钟 · 3 轮)
|
Docker 桥接网络
| | | |
Java:8080 Go:8081 Python:8082 Node:8083
| | | |
[calculate_fibonacci · fetch_external_data]
[process_json_data · simulate_db_query ]
|
监控指标:延迟 · 每秒请求数 · CPU 使用率 · 内存
测试结果
核心数据表格:
服务器 平均延迟 吞吐量(RPS) CPU 使用率 内存
Java 0.84 毫秒 1,624 28.8% 226 MB
Go 0.86 毫秒 1,624 31.8% 18 MB
Node.js 10.66 毫秒 559 98.7% 110 MB
Python 26.45 毫秒 292 93.9% 98 MB
Java 和 Go 完全是另一个量级:
•
平均延迟 亚毫秒级
•
每秒处理超 1600 请求
•
CPU 使用率轻松控制在 35% 以内
而 Python:
•
平均延迟 26.45 毫秒
•
吞吐量仅 292 RPS
•
CPU 直接跑满到 近 94%
最惊人的单项结果来自 tools_list 接口——这只是一个列出可用工具的基础元数据接口,理论上开销极低:
•
Java:0.31 毫秒
•
Python:28.88 毫秒
差距达到 93 倍。
Python 性能拉胯的原因
简单说:GIL(全局解释器锁)。它会阻止 CPU 密集型任务的真正并行执行。
在高并发压力下,async/await 只能实现 I/O 并发,但需要真实计算的任务会排队、串行执行,最终导致高延迟与 CPU 跑满。
# Python — FastMCP
@mcp.tool()
async def calculate_fibonacci(n: int) -> dict:
result = fibonacci(n) # GIL 会阻塞并发 CPU 计算
return {"result": result, "server": "python"}
Go 的 goroutine 模型则完全不同:
// Go — Official SDK
server.AddTool("calculate_fibonacci", mcp.Tool{...},
func(args map[string]interface{}) (*mcp.ToolResponse, error) {
n := int(args["n"].(float64))
// goroutine 原生处理并发 — 无 GIL,无瓶颈
return &mcp.ToolResponse{Content: [...]}, nil
})
两种并发模型底层设计完全不同,在持续高并发下,差距会被不断放大。
单接口延迟明细
基准测试还按接口拆分了延迟,呈现出非常清晰的规律:
接口 Java Go Node.js Python
calculate_fibonacci 0.37 ms 0.39 ms 7.11 ms (19倍) 30.83 ms (84倍)
fetch_external_data 1.32 ms 1.29 ms 19.18 ms (15倍) 80.92 ms (63倍)
process_json_data 0.35 ms 0.44 ms 7.48 ms (21倍) 34.24 ms (97倍)
simulate_db_query 10.37 ms 10.71 ms 26.71 ms (2.6倍) 42.57 ms (4.1倍)
tools_list 0.31 ms 0.72 ms 7.56 ms (24倍) 28.88 ms (93倍)
•
simulate_db_query(等待型模拟查询):差距最小,因为大家“等待”的速度差不多。
•
计算型、I/O 型任务:差距直接爆炸,运行时的并发模型优劣一目了然。
必须注意的客观说明
1
Node.js 说明测试中 Node.js 服务为了修复 CVE-2026–25536(并发请求间会话数据泄露),采用了每次请求新建实例的安全方案,这本身就带来额外开销。如果使用共享实例模式,性能会明显更好。本次结果反映的是安全加固后的配置,而非 Node.js 性能上限。
2
Python 说明Python 使用的是单进程 uvicorn 默认配置。如果采用多进程 + uvloop 等生产级优化,吞吐量会有可观提升。
也就是说:本次测试对比的是贴近真实开箱即用的默认配置,而非极致优化的生产环境。对 Python、Node.js 做过深度调优的团队,实际表现会更好。
另外一个所有语言都一致的结论:**390 万次请求全部成功,零错误。**MCP 协议本身非常稳定可靠。
对技术选型的真实意义
•
如果你在做:内部工具、面向开发者的 MCP 服务、原型DemoPython 和 Node.js 完全合理。开发效率高、生态丰富,低流量下用户几乎感知不到延迟差异。
•
如果你要上:生产环境、高并发流量成本账会立刻变天。支撑相同流量,Python 需要的 CPU 资源大约是 Go 的 5 倍。规模化部署时,这是实打实的基础设施成本。
综合来看:
•
Go:生产环境的务实首选。性能与 Java 相当,内存占用只有 Java 的 1/12,无 JVM 预热,测试稳定性极高(吞吐量波动仅 0.5%)。
•
Java:适合追求极致低延迟、且已有 JVM 技术栈的团队。
•
Python / Node.js:更适合低流量场景、开发调试环境。
这项测试并没有爆出什么“颠覆性发现”——语言运行时本来就有性能差异。但它用硬核数据,把开发者常当作“风格偏好”的技术选型,变成了可量化、可落地的工程决策。
-------------------------------------------------------------