本文进行实际测试 FastAPI 的并发能力,即同时能处理多少个请求,另外还能接收多少请求放在等待队列当中; 并找到如何改变默认并发数; 以及它是如何运用线程或进程来处理请求。我们可以此与 Flask 进行对比,参考 Python Flask 框架的并发能力及线,进程模型,是否真如传说中所说的 FastAPI 性能比 Flask 强, FastAPI 是否对得起它那道闪电的 Logo。
本文使用 JMeter 进行测试,测试机器为 MacBook Pro, CPU 6 核超线程,内存 16 Gb。
对于每一种类型 Web 服务基本的测试是每秒发送 2 个请求,连续发送 1000 个,500 秒发送完所有请求,程序中 API 方法接受到请求后 sleep 800 秒,保证在全部 1000 个请求送出之前一直占着连接,并有充足的时间对连接进行分析。在测试极端并发数时,由于在 Mac OS X 尽管设置了 ulimit 最多也只能创建 4000 多一点线程,所以在模拟更多用户数时,JMeter 在远程 Linux(Docker 或虚拟机) 上运行测试用例。
请求的 URL 是 http://localhost:8080/?id=${count}, 带一个自增序列用以识别不同的请求, JMeter 的 Thread Group 配置为 Number of Threads (users): 1000, Ramp-up period (seconds): 500
首先安装依赖
pip install fastapi
pip install uvicorn[standard]
当前安装的最新版本 fastapi0.94.1, uvicorn0.21.1
测试同步方法
app.py
from fastapi import FastAPI, Query
import threading
import time
from datetime import datetime
import os
import uvicorn
app = FastAPI()
global_request_counter = 0
@app.get("/")
def index(request_id: str = Query(..., alias="id")):
global global_request_counter
global_request_counter += 1
thread_name = threading.current_thread().name
print(f"{
datetime.now()} - {
os.getpid()}-{
thread_name}: #{
global_request_counter} processing request id[{
request_id}], sleeping...")
time.sleep(800)
print(f"{
datetime.now()} - {
os.getpid()}-{
thread_name}: done request id[{
request_id}]")
return "hello"
# 或者用命令方式启动 uvicorn app:app --host 0.0.0.0 --port 8080
if __name__ == '__main__':
uvicorn.run