本内容是对知名性能评测博主 Anton Putra Python (FastAPI) vs Go (Golang) Performance Benchmark 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准
在本视频中,我们将对比 FastAPI (Python 生态中最快的 Web 框架之一)和 Golang 标准库的性能。
第一轮测试
为了建立基准,我们的第一轮测试仅测试框架本身的性能:
-
每个应用程序都会返回 硬编码对象 ,并以 JSON 格式 响应客户端。
-
我们将测量以下关键指标:
- 99% 分位数的延迟
- 每秒请求数(Requests per Second, RPS)
- CPU 使用率
- 内存使用率
- 错误率(可用性)
- CPU 限流(CPU Throttling)
由于我们会在 AWS 上的生产级 Kubernetes 集群 部署这些应用程序,因此测试环境尽可能贴近真实生产环境。
第二轮测试
第二轮测试更加有趣:
- 当应用程序收到 POST 请求 时:
- 解析请求体。
- 生成 UUID 和时间戳。
- 将记录插入 关系型数据库(PostgreSQL)。
- (新增)使用缓存系统:在插入数据库后,将对象(包括数据库生成的 ID)存入缓存。
本次测试首次加入了缓存 ,我选择了 Memcached ,因为它的性能更高。但如果你感兴趣,可以在另外的视频中看到它与 Redis 的对比。
为了更细致地分析性能,我使用 Prometheus 监测每个应用的关键操作,例如 数据库插入 和 缓存存取。此外,我们还会测量:
- PostgreSQL 和 Memcached 的 CPU 使用率
- 每个应用程序创建的数据库连接池大小
测试环境
所有测试都在 AWS 运行:
- Memcached 部署在 m7a.xlarge 实例。
- PostgreSQL 部署在 2xlarge 专用 EC2 实例。
- EKS 集群 :
- 第一组节点 :使用 m7a.large 通用实例 运行应用程序。
- 第二组节点 :使用 Graviton 计算优化实例 部署 Prometheus 、Grafana 和用于生成负载的客户端。
计算优化实例的硬件与通用实例相同,但 内存更少,每小时价格便宜 $0.10。由于测试不需要太多内存,所以我尽可能优化成本。
第一轮测试
开始执行第一轮测试。
这轮测试没有任何依赖项,甚至没有业务逻辑,仅仅是返回硬编码的数据给客户端。
从一开始,你就能看到 性能上的巨大差异:
- 客户端测量的延迟 :FastAPI的延迟至少是Go 应用程序 的 两倍。

- CPU 使用率 :
- 在过去的测试中,Python 应用的 CPU 使用率通常远高于其他语言。
- FastAPI 在 13,000 RPS 左右开始跟不上,无法处理更多请求。
- 由于 CPU 资源耗尽,Kubernetes 开始对 FastAPI 进行限流,导致其延迟大幅上升。

- Go 应用在 25,000 RPS 时,FastAPI 彻底崩溃 :
- Python 服务器过载,导致 可用性降至 0。
- 客户端请求要么超时,要么返回 500 错误。
- 在 FastAPI 彻底崩溃期间,客户端不会收到响应,因此延迟图表上会出现空白。

从性能表现来看,FastAPI 的表现类似于 Django,甚至只稍微好一点。
如果你有优化方案,欢迎提交 Pull Request ,我会重新测试。但到目前为止,我对 FastAPI 的表现感到失望,本来期望它的性能会更好。
接下来,我让测试继续运行,直到 Go 应用达到极限:
- Go 应用的 RPS 在 60,000 - 62,000 之间,和我之前的基准测试非常一致。
- 在 Kubernetes 运行 Go 应用 时,建议限制 Go 用户线程数,这样 Kubernetes 就不会对其进行过多的限流。

第一轮测试结果
1. 每秒请求数(RPS)
- FastAPI 最高达到 13,000 RPS。
- Go 最高达到 62,000 RPS。

2. 客户端延迟
- FastAPI 失败时,延迟图表会出现空白。
- Go 的整体延迟远低于 FastAPI。

3. CPU 使用率
- FastAPI 在前 10-15 分钟内就达到 CPU 上限,并开始性能下降。

4. 可用性
- 计算方式:成功请求数 / 总请求数。
- FastAPI 崩溃后,可用性直接降为 0。

5. 内存使用
- Go 在崩溃前,内存使用量会激增。

6. CPU 限流
- FastAPI 的 CPU 限流现象更严重 ,因为它很快就耗尽了 CPU 资源。

第二轮测试
在这轮测试中,我们首次引入缓存:
- 每当应用收到请求:
- 解析请求体。
- 插入 PostgreSQL。
- 将数据存入 Memcached。
为什么选 Memcached 而不是 Redis?
- Memcached 更高效,可以使用更小的实例,节省基础设施成本。
第二轮测试结果
第一次运行测试时:

- FastAPI 仅使用 60% 的 CPU(2 个 Worker 进程)。
- 由于大量 I/O 操作 (数据库 & 缓存),我增加 Worker 进程至 4 ,CPU 使用率提升至 80%。
1. RPS
- FastAPI 仅能处理 800 RPS,表现远远落后于 Go。
2. 数据库 & 缓存操作
- Go 的数据库和缓存操作延迟明显更低。
- POST 请求的整体延迟也更低。

3. 资源限制
- FastAPI 在 10-15 分钟内达到极限 ,而 Go 需要运行 1 小时才能达到极限。
4. PostgreSQL 和 Memcached 监控
- 测量 PostgreSQL 和 Memcached 的 CPU 使用率。
- 应用程序数据库连接池大小 :
- 每个应用的连接池限制为 500 。
- 数据库最大连接数增加到 1000+ 。
5. Go 在 35,000 RPS 时失败
-
原因 :我忘了增加 Linux 服务器的 文件描述符限制(file descriptor limit)。
-
若优化文件描述符,Go 还能处理更多请求 ,但FastAPI 远远不在同一水平线上,所以我没必要重新测试。
最终结果
打开测试图表:
- 每秒请求数

- POST 请求延迟
Go最后的延迟峰值是由于文件描述符造成的

- 数据库延迟

- Memcached 延迟

- 应用程序 CPU 使用率

- PostgreSQL 和 Memcached CPU 使用率

- 连接池大小

- 内存使用情况

如果你有优化方案,欢迎查看视频描述中的源代码链接 。
我原本期待 FastAPI 的性能更好,希望有人能优化它。
如果你对 Rust vs Go 等其他基准测试感兴趣,可以查看我的频道。
谢谢观看,我们下次见!