测试基本信息

主题:比较异步框架和同步框架在数据库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请求

get 请求:

压测结果

并发量:225

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请求创建一个用户

get请求

压测结果

并发量:1496

性能对比

并发曲线图对比:

参数对比:

框架 数据库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任务压测对比的更多相关文章

  1. python高级编程之 web静态服务器

    返回固定数据 import socket def request_handler(new_client_socket): """ 响应客户端请求的核心函数 "& ...

  2. python异步编程之asyncio

    python异步编程之asyncio   前言:python由于GIL(全局锁)的存在,不能发挥多核的优势,其性能一直饱受诟病.然而在IO密集型的网络编程里,异步处理比同步处理能提升成百上千倍的效率, ...

  3. 异步编程之Promise(3):拓展进阶

    异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2):探究原理 异步编程之Promise(3):拓展进阶 异步编程之Generator(1)--领略魅 ...

  4. 异步编程之Promise(2):探究原理

    异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2):探究原理 异步编程之Promise(3):拓展进阶 异步编程之Generator(1)--领略魅 ...

  5. 200行自定义异步非阻塞Web框架

    Python的Web框架中Tornado以异步非阻塞而闻名.本篇将使用200行代码完成一个微型异步非阻塞Web框架:Snow. 一.源码 本文基于非阻塞的Socket以及IO多路复用从而实现异步非阻塞 ...

  6. Tornado----自定义异步非阻塞Web框架:Snow

    Python的Web框架中Tornado以异步非阻塞而闻名.本篇将使用200行代码完成一个微型异步非阻塞Web框架:Snow. 一.源码 本文基于非阻塞的Socket以及IO多路复用从而实现异步非阻塞 ...

  7. 150行代码搭建异步非阻塞Web框架

    最近看Tornado源码给了我不少启发,心血来潮决定自己试着只用python标准库来实现一个异步非阻塞web框架.花了点时间感觉还可以,一百多行的代码已经可以撑起一个极简框架了. 一.准备工作 需要的 ...

  8. 异步编程之Generator(1)——领略魅力

    异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2):探究原理 异步编程之Promise(3):拓展进阶 异步编程之Generator(1)--领略魅 ...

  9. (翻译)异步编程之Promise(1):初见魅力

    原文:https://www.promisejs.org/ by Forbes Lindesay 异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2) ...

  10. net异步编程之await

    net异步编程之await 初探asp.net异步编程之await   终于毕业了,也顺利进入一家期望的旅游互联网公司.27号入职.放肆了一个多月没写代码,好方啊. 另外一下观点均主要针对于await ...

随机推荐

  1. nginx中的proxy_pass配置

    Nginx 是最常用的反向代理工具之一,一个指令 proxy_pass搞定反向代理,对于接口代理.负载均衡很是实用,但 proxy_pass指令后面的参数很有讲究,通常一个/都可能引发一个血案. 通常 ...

  2. Qt源码阅读(四) 事件循环

    事件系统 文章为本人理解,如有理解不到位之处,烦请各位指正. @ 目录 事件系统 什么是事件循环? 事件是如何产生的? sendEvent postEvent 事件是如何处理的? 事件循环是怎么遍历的 ...

  3. sync.Pool:提高Go语言程序性能的关键一步

    1. 简介 本文将介绍 Go 语言中的 sync.Pool并发原语,包括sync.Pool的基本使用方法.使用注意事项等的内容.能够更好得使用sync.Pool来减少对象的重复创建,最大限度实现对象的 ...

  4. PyInstaller打包的文件闪退

    问题描述:使用PyInstaller打包的pycharm写的python程序,打包好后从windows上打开一直闪退 一.双击exe文件闪退,从cmd命令行中与加载程序,可以看到具体的报错 D:\di ...

  5. 这样也行,在lambda表达式中优雅的处理checked exception

    目录 简介 lambda表达式中的checked exception lambda中的unchecked exception 对lambda的最终改造 总结 简介 最近发现很多小伙伴还不知道如何在la ...

  6. API 网关日志的价值,你了解多少?

    本文介绍了 API 网关日志的价值,并以知名网关 Apache APISIX 为例,展示如何集成 API 网关日志. 作者钱勇,API7.ai 技术工程师,Apache APISIX Committe ...

  7. Active Record Associations

    The Types of Associations 在 Rails 中,可以通过 ActiveRecord 来定义不同类型的关联关系(Associations),包括以下几种: belongs_to: ...

  8. vue-cli3构建和发布 实现分环境打包步骤(给不同的环境配置相对应的打包命令)

    https://panjiachen.github.io/vue-element-admin-site/zh/guide/essentials/deploy.html#%E6%9E%84%E5%BB% ...

  9. 【深入浅出 Yarn 架构与实现】6-3 NodeManager 分布式缓存

    不要跳过这部分知识,对了解 NodeManager 本地目录结构,和熟悉 Container 启动流程有帮助. 一.分布式缓存介绍 主要作用就是将用户应用程序执行时,所需的外部文件资源下载缓存到各个节 ...

  10. 【Ubuntu】2. 安装Ubuntu操作系统+VMware Tools

    接上一篇,这一部分介绍了操作系统的安装 开启虚拟机,首先由四个选项,选第一个正常安装即可,这里稍等片刻就可以进入安装选项 到了这一步的话可以在左侧设置系统语言,我的英语比较垃圾就选中文了,选择完之后点 ...