FastAPI真香?一个Java转Python小厂后端的实战手记
去年双11前夜,我们老板突然在钉钉群里@我:“小王,下个月我们要上线一个数据聚合平台,你用Python搞个后端,别整那些花里胡哨的,快点就行。”我盯着消息愣了三秒——我可是写了五年Java的“老码农”,Spring Boot 都能闭眼写,现在让我切 Python?而且 deadline 只有四周?
更离谱的是,产品经理还加了一句:“对了,要支持爬虫结果的实时查询和导出。”我差点把咖啡杯捏碎。但没办法,小厂没人权,只能硬着头皮上。
一番调研后,我放弃了 Django(太重)和 Flask(异步支持弱),最终锁定了 FastAPI。没想到,这一试,还真有点上头。
为啥选 FastAPI?不只是因为“快”
说实话,一开始我对 Python Web 框架的印象还停留在“玩具级”——直到看到 FastAPI 的官方 benchmark。它基于 Starlette(ASGI)和 Pydantic,天生支持异步,性能直逼 Go 和 Node.js,甚至在某些场景下比我们老项目里的 Spring Boot 还快(别告诉 Java 组的老李,他正为 GC 调优掉头发)。
更重要的是,自动生成 OpenAPI 文档这个功能,直接拯救了我和前端同事的关系。以前每次改接口都要手动写 Swagger 注解,现在只要定义好 Pydantic 模型,文档自动同步,前端再也不用追着我问“字段是不是 string 啊?”。
爬虫数据接入:从阻塞到异步的血泪教训
我们的核心需求之一是接入内部爬虫系统抓取的商品价格数据。最初我图省事,直接在接口里调用 requests.get():
@app.get("/price/{item_id}")
def get_price(item_id: str):
resp = requests.get(f"http://crawler-service/api/price/{item_id}")
return resp.json()
结果压力一上来,整个服务直接卡死。为啥?requests 是同步阻塞的!一个请求卡住,其他全排队。这在 Java 里我们早用 CompletableFuture 或 WebFlux 解决了,但在 Python 世界,得换 async。
于是赶紧重构,换成 httpx(支持 async):
import httpx
@app.get("/price/{item_id}")
async def get_price(item_id: str):
async with httpx.AsyncClient() as client:
resp = await client.get(f"http://crawler-service/api/price/{item_id}")
return resp.json()
加上 async/await 后,单机 QPS 从 80 直接飙到 1200+(本地压测数据)。小厂服务器就两台,这波优化省了至少一台机器的钱——老板看我的眼神都温柔了。
模型验证:Pydantic 是真的强
以前在 Java 里,校验参数得靠 Hibernate Validator,写一堆 @NotNull、@Min(0),烦死了。FastAPI 用 Pydantic 定义模型,验证逻辑天然集成:
from pydantic import BaseModel, validator
class PriceQuery(BaseModel):
item_ids: List[str]
source: str = "default"
@validator("item_ids")
def check_item_ids(cls, v):
if len(v) > 100:
raise ValueError("最多查询100个商品")
return v
然后在接口里直接用:
@app.post("/batch_price")
async def batch_price(query: PriceQuery):
# 自动校验 + 类型转换
...
非法请求直接返回 422 错误,连 try-catch 都省了。测试同学第一次跑自动化就过了,感动得请我喝了杯瑞幸。
部署上线:小厂运维的“极限操作”
我们没 K8s,没 Helm,只有两台 CentOS 物理机。FastAPI 推荐用 Uvicorn + Gunicorn 部署:
gunicorn -k uvicorn.workers.UvicornWorker main:app -w 4 -b 0.0.0.0:8000 --timeout 120
但这里有个坑:默认 worker 数是 CPU 核数。我们服务器是 8 核,但跑着 MySQL、Redis 和爬虫调度器,实际给 FastAPI 分 4 个 worker 刚好。多了反而因上下文切换拖慢性能。
另外,超时时间一定要调大!因为爬虫服务偶尔会慢(网络抖动 or 对方反爬),默认 30 秒不够用。线上第一次挂就是因为 timeout,半夜被 PagerDuty 叫醒,真是栓Q。
性能对比:FastAPI vs 我们的 Java 服务
出于好奇,我拿同一个接口(查商品价格)做了对比测试(4核8G,同机房):
| 框架 | 平均延迟 (ms) | P99 延迟 (ms) | 最大 QPS |
|---|---|---|---|
| Spring Boot 2.7 | 45 | 180 | 950 |
| FastAPI + Uvicorn | 28 | 110 | 1320 |
当然,Java 服务做了很多业务逻辑(权限校验、日志审计等),而 FastAPI 版本相对轻量。但即便如此,FastAPI 在 I/O 密集型场景(比如调爬虫、查 DB)的优势非常明显。
给 Java 转 Python 后端的建议
如果你像我一样,是从 Java 转过来的,记住几点:
- 别用同步库:任何可能阻塞的操作(HTTP、DB、文件读写)都找 async 替代品。比如数据库用
asyncpg或SQLAlchemy 1.4+ async。 - 类型注解不是可选项:FastAPI 重度依赖类型提示做序列化和文档生成,不写等于自断一臂。
- 别迷信“Python 慢”:在 I/O 密集型服务中,Python + async 的吞吐完全不输 Java,甚至更省资源。
尾声:通勤路上的思考
现在每天坐地铁回家(北京回龙观→国贸,1小时起步),我都会想:技术栈真的有高低吗?FastAPI 让我两周搞定原本要一个月的活,还顺手把爬虫数据 API 化了,测试覆盖率从 30% 提到 80%。而隔壁组还在为 Spring Cloud Config 的刷新问题吵架。
小厂资源有限,能快速交付、稳定运行、便于维护的技术,就是好技术。FastAPI 不是银弹,但它确实让我这个“Java 老兵”重新爱上了写后端。
下次如果产品再说“加个简单接口”,我可能会笑着回答:“行,今晚就能上线——只要别再提爬虫。”
(完)
附:我的 VSCode 插件清单(Python 开发必备)
- Python(官方)
- Pylance(智能提示)
- autoDocstring(自动生成文档字符串)
- REST Client(直接在编辑器里测 API)
- Error Lens(错误高亮,救我狗命)
装完这些,写 FastAPI 真的像开了挂。

评论 0