经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python » 查看文章
Python异步编程之web框架 异步vs同步 数据库IO任务压测对比
来源:cnblogs  作者:金色旭光  时间:2023/6/8 9:25:52  对本文有异议

image

测试基本信息

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

flask 同步框架

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

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

api接口

  1. from flask import Flask, request
  2. from sqlalchemy.orm import sessionmaker
  3. from model import Student, engine, Base
  4. app = Flask(__name__)
  5. @app.route('/users')
  6. def list_all():
  7. session = sessionmaker(engine)() # 构建session对象
  8. students = session.query(Student).all()
  9. res = [stu.name for stu in students]
  10. session.close()
  11. return res
  12. @app.route("/user", methods=["POST"])
  13. def create():
  14. session = sessionmaker(engine)() # 构建session对象
  15. student = Student(name='Tony') # 创建一个student对象
  16. session.add(student) # 添加到session
  17. session.commit() # 提交到数据库
  18. session.close()
  19. return {"res":"success"}
  20. if __name__ == '__main__':
  21. app.run(port=8090, host="0.0.0.0")

接口调用

post请求
image

get 请求:
image

压测结果

并发量:225
image

starlette 异步框架

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

  1. pip install tortoise-orm
  2. pip install aiomysql

定义表结构

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

api接口

  1. from model import Users
  2. from starlette.applications import Starlette
  3. from tortoise.contrib.starlette import register_tortoise
  4. from starlette.requests import Request
  5. from starlette.responses import JSONResponse
  6. from uvicorn.main import run
  7. app = Starlette()
  8. # 查询记录
  9. @app.route("/user", methods=["GET"])
  10. async def list_all(_: Request):
  11. users = await Users.all()
  12. return JSONResponse({"users": [str(user) for user in users]})
  13. # 创建记录
  14. @app.route("/user", methods=["POST"])
  15. async def create(request: Request):
  16. body = await request.json
  17. username = body.get("user_name")
  18. user = await Users.create(username=username)
  19. return JSONResponse({"ret":"success"})
  20. # 表迁移
  21. register_tortoise(app, db_url="mysql://root:123456@127.0.0.1:3306/test", modules={"models": ["model"]}, generate_schemas=True)
  22. if __name__ == "__main__":
  23. run(app, host="0.0.0.0")

接口调用

post请求创建一个用户
image

get请求
image

压测结果

并发量:1496
image

image

性能对比

并发曲线图对比:
image

参数对比:

框架 数据库IO 延迟 纯框架无IO 文件IO
fastapi 225 47 ms 463 453
starlette 1496 6 ms 1539 1538

总结

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

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

原文链接:https://www.cnblogs.com/goldsunshine/p/17464743.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号