一、为什么突然想做这个对比
最近在给团队做技术选型,聊到并发模型的时候,大家各执一词。有人说 Python 协程天下无敌,有人说 Java 线程池才是王道,还有人觉得 PHP-FPM 虽然老派但胜在稳定。与其在会议室里争得面红耳赤,不如直接拉出来跑一轮压力测试,用数据说话。
这篇文章就把整个测试过程记录下来,包括环境准备、压测脚本、结果数据,以及我个人的一些思考。如果你也在纠结类似的问题,希望能给你一些参考。
二、测试环境与准备
先交代一下硬件和软件环境,避免结果失真。测试机是一台 4 核 8G 的云服务器,操作系统是 CentOS 7.9。压测工具用的是 wrk,单机并发能力足够,而且结果输出很直观。
三个被测对象分别是:
- Python 协程:使用 FastAPI + uvicorn,异步接口模拟数据库查询耗时 50ms。
- Java 线程池:Spring Boot 内嵌 Tomcat,线程池核心线程数 200,接口同样模拟 50ms 阻塞。
- PHP-FPM:LNMP 环境,PHP 7.4,接口用 sleep(0.05) 模拟耗时。
每个服务都只提供一个最简单的接口,不做任何业务逻辑,纯粹看框架本身的并发处理能力。
三、压测脚本与代码
先看 Python 这边的代码。FastAPI 的异步接口写起来很简洁,用asyncio.sleep模拟 IO 等待:
import asyncio from fastapi import FastAPI app = FastAPI() @app.get("/test") async def test(): await asyncio.sleep(0.05) return {"status": "ok"}Java 这边用 Spring Boot,接口内部让线程睡 50ms,模拟真实业务中的阻塞操作:
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @GetMapping("/test") public String test() throws InterruptedException { Thread.sleep(50); return "ok"; } }PHP 这边最简单,一个文件搞定:
<?php usleep(50000); echo "ok"; ?>压测命令统一用 wrk,参数保持一致,方便横向对比。每个服务先预热 10 秒,再正式压测 30 秒,并发数从 100 起步,逐步加到 500:
wrk -t4 -c100 -d30s http://127.0.0.1:8080/test四、测试结果与数据对比
先看并发 100 的情况。Python 协程的 QPS 大概在 1900 左右,Java 线程池在 1800 上下,PHP-FPM 则只有 700 多。这个结果其实不意外,协程在 IO 密集场景下的优势确实明显。
把并发拉到 300 的时候,差距开始拉大。Python 协程依然稳定在 1900 附近,Java 线程池掉到了 1500,PHP-FPM 直接跌到 500 以下。这时候能明显感觉到 PHP-FPM 的进程模型在高并发下的瓶颈。
最后试了并发 500,Python 协程还能扛住 1800 左右,Java 线程池已经降到 1200,PHP-FPM 只剩 300 出头。而且 PHP 这边的响应时间抖动非常厉害,p99 延迟已经到了好几秒。
把数据整理成表格更直观:
| 并发数 | Python 协程 QPS | Java 线程池 QPS | PHP-FPM QPS |
|---|---|---|---|
| 100 | 1900 | 1800 | 720 |
| 300 | 1900 | 1500 | 480 |
| 500 | 1800 | 1200 | 320 |
五、结果分析与思考
说实话,这个结果在我的预期之内,但也有一些值得玩味的地方。Python 协程在 IO 密集场景下确实能打,单线程处理海量连接的能力是它的核心优势。但要注意,协程对 CPU 密集任务并不友好,如果业务里有大量计算,效果会大打折扣。
Java 线程池的表现中规中矩,胜在稳定和生态成熟。线程数调优是个技术活,调好了性能不俗,调不好反而会拖垮服务。而且线程本身有内存开销,200 个线程光栈空间就要吃掉不少内存。
PHP-FPM 的劣势很明显,但也不能一棍子打死。它的部署简单、上手快,中小流量的业务完全够用。而且 PHP 的生态摆在那里,很多老项目迁移成本太高,继续用 PHP 也是合理的选择。
最后想说的是,技术选型不能只看压测数据。团队的技术栈、运维能力、业务特点都要考虑进去。压测数据只是参考,不是唯一标准。