Python异步编程之web框架 异步vs同步 数据库IO任务并发支持对比

如果你不相信努力和时光,那么成果就会是第一个选择辜负你的。不要去否定你自己的过去,也不要用你的过去牵扯你现在的努力和对未来的展望。不是因为拥有希望你才去努力,而是去努力了,你才有可能看到希望的光芒。Python异步编程之web框架 异步vs同步 数据库IO任务并发支持对比,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

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操作。
定义表结构

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine, Column, Integer, String

DB_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, request
from sqlalchemy.orm import sessionmaker
from model import Student, engine, Base


app = 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请求
image

get 请求:
image

压测结果

并发量:225
image

starlette 异步框架

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

pip install tortoise-orm
pip install aiomysql

定义表结构

from tortoise import fields, models


class 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 Users
from starlette.applications import Starlette
from tortoise.contrib.starlette import register_tortoise
from starlette.requests import Request
from starlette.responses import JSONResponse
from uvicorn.main import run


app = 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请求创建一个用户
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异步编程的文章。包括同异步框架性能对比、异步事情驱动原理等。首发微信公众号,欢迎关注第一时间阅读。
Python异步编程之web框架 异步vs同步 数据库IO任务并发支持对比

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/196509.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!