Python异步编程之web框架 异步vs同步 数据库IO任务压测对比

来源:博客园       时间:2023-06-08 10:06:55

测试基本信息

主题:比较异步框架和同步框架在数据库IO操作的性能差异python版本:python 3.8数据库:mysql 8.0.27 (docker部署)压测工具:locustweb框架:同步:flask 异步:starlette请求并发量: 模拟10个用户服务器配置: Intel(R) i7-12700F客户端配置:Intel(R) i7-8700 3.20GHz

flask 同步框架

python中操作数据库通常使用ORM框架完成。flask 使用的ORM框架是大名鼎鼎的sqlalchemy,该框架是所有ORM框架中生态最完善的,但是sqlalchemy对异步的支持并不算友好,目前支持原生SQL操作。定义表结构


【资料图】

from sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy import create_engine, Column, Integer, StringDB_URI = "mysql+pymysql://root:123456@127.0.0.1:3306/test"engine = create_engine(DB_URI)Base = declarative_base(engine)  # SQLORM基类class Student(Base):    __tablename__ = "student"  # 表名    id = Column(Integer, primary_key=True, autoincrement=True)    name = Column(String(50))Base.metadata.create_all()  # 将模型映射到数据库中

api接口

from flask import Flask, requestfrom sqlalchemy.orm import sessionmakerfrom model import Student, engine, Baseapp = Flask(__name__)@app.route("/users")def list_all():    session = sessionmaker(engine)()  # 构建session对象    students = session.query(Student).all()    res = [stu.name for stu in students]    session.close()    return res@app.route("/user", methods=["POST"])def create():    session = sessionmaker(engine)()  # 构建session对象    student = Student(name="Tony")  # 创建一个student对象    session.add(student)  # 添加到session    session.commit()  # 提交到数据库    session.close()    return {"res":"success"}if __name__ == "__main__":    app.run(port=8090, host="0.0.0.0")
接口调用

post请求

get 请求:

压测结果

并发量:225

starlette 异步框架

starlette 异步框架配套使用的ORM框架是 tortoise-orm。tortoise-orm 是一款方便、易用、可靠的异步ORM框架,文档:https://tortoise.github.io/安装数据库

pip install tortoise-ormpip install aiomysql

定义表结构

from tortoise import fields, modelsclass Users(models.Model):    id = fields.IntField(pk=True)    username = fields.CharField(max_length=20)    def __str__(self) -> str:        return f"User {self.id}: {self.username}"

api接口

from model import Usersfrom starlette.applications import Starlettefrom tortoise.contrib.starlette import register_tortoisefrom starlette.requests import Requestfrom starlette.responses import JSONResponsefrom uvicorn.main import runapp = Starlette()# 查询记录@app.route("/user", methods=["GET"])async def list_all(_: Request):    users = await Users.all()    return JSONResponse({"users": [str(user) for user in users]})# 创建记录@app.route("/user", methods=["POST"])async def create(request: Request):    body = await request.json    username = body.get("user_name")    user = await Users.create(username=username)    return JSONResponse({"ret":"success"})# 表迁移register_tortoise(app, db_url="mysql://root:123456@127.0.0.1:3306/test", modules={"models": ["model"]}, generate_schemas=True)if __name__ == "__main__":    run(app, host="0.0.0.0")
接口调用

post请求创建一个用户

get请求

压测结果

并发量:1496

性能对比

并发曲线图对比:

参数对比:

框架数据库IO延迟纯框架无IO文件IO
fastapi22547 ms463453
starlette14966 ms15391538
总结

在数据库读写方面,异步框架性能是同步框架的6倍,可以看出同步框架在数据库读写频繁时性能下降明显,几乎是无IO读写的一半,而异步框架在有数据库IO的情况下并发几乎保持不变。主要原因是在当前简单的场景下数据库读操作耗时少而连接释放耗时较多,异步编程非阻塞模型不等待,所以数据库连接释放耗时并不阻塞异步框架。下一篇比较redis IO的并发性能。

连载一系列关于python异步编程的文章。包括同异步框架性能对比、异步事情驱动原理等。首发微信公众号,欢迎关注第一时间阅读。

关键词:

上一篇:即时看!长安汽车5月销量200197辆 同比增长32.49%
下一篇:最后一页