2023年是时候更新你的技术武器库了AsgivsWsgi(FastAPIvsFlask)
也许这一篇的标题有那么一点不厚道,因为Asgi(Asynchronous Server Gateway Interface)毕竟是Wsgi(Web Server Gateway Interface)的扩展,而FastAPI毕竟也是站在Flask的肩膀上才有了突飞猛进的发展,大多数人听说Asgi也许是因为Django的最新版(3.0)早已宣布支持Asgi网络规范,这显然是一个振奋人心的消息,2023年,如果你在Web开发面试中不扯一点Asgi,显然就有点落后于形势了。
那么到底啥是Wsgi,什么又是Asgi,放心,不扯CGI,不扯各种抽象概念,简单粗暴理解:
Wsgi是同步通信服务规范,客户端请求一项服务,并等待服务完成,只有当它收到服务的结果时,它才会继续工作。当然了,可以定义一个超时时间,如果服务在规定的时间内没有完成,则认为调用失败,调用方继续工作。
Wsgi简单工作原理示意图:
简单实现: #WSGI example def application(environ, start_response): start_response("200 OK", [("Content-Type", "text/plain")]) return b"Hello, Wsgi "
Asgi是异步通信服务规范。客户端发起服务呼叫,但不等待结果。调用方立即继续其工作,并不关心结果。如果调用方对结果感兴趣,有一些机制可以让其随时被回调方法返回结果。
Asgi简单工作原理示意图:
简单实现: #Asgi example async def application(scope, receive, send): event = await receive() ... await send({"type": "websocket.send", ...})
简单总结一下:Asgi是异步的,Wsgi是同步的,而基于Wsgi的Flask是同步框架,基于Asgi的FastAPI是异步框架,就这么简单,那么同步框架和异步框架的区别到底在哪儿?为什么要把Flask换成FastAPI?
不靠拍脑门儿、也不是道听途说、人云亦云。玩技术的应该用数据说话,论点永远依托论据,所以我们来简单对两款框架的性能做一个测试,首先分别安装依赖的库。
Flask: pip install gunicorn pip install gevent pip install flask
FastAPI: pip install fastapi pip install uvicorn
我们首先干的一件事就是,看看Flask和FastAPI如何处理来自多个客户端的多个请求。特别是当代码存在效率问题时(比如数据库查询时间长这种耗时任务),这里故意使用time.sleep()来模拟耗时任务,为什么不用asyncio呢?因为众所周知的原因:time.sleep是阻塞的。
Flask: from flask import Flask from flask_restful import Resource, Api from time import sleep app = Flask(__name__) api = Api(app) class Root(Resource): def get(self): print("睡10秒") sleep(10) print("醒了") return {"message": "hello"} api.add_resource(Root, "/") if __name__ == "__main__": app.run()
FastApi: import uvicorn from fastapi import FastAPI from time import sleep app = FastAPI() @app.get("/") async def root(): print("睡10秒") sleep(10) print("醒了") return {"message": "hello"} if __name__ == "__main__": uvicorn.run(app, host="127.0.0.1", port=8000)
分别启动服务
Flask:python3 manage.py
FastAPI:uvicorn manage:app --reload
同时一时间内,开启多个浏览器,分别并发请求首页 。
Flask:http://localhost:5000
FastAPI:http://localhost:8000
观察后台打印结果:
Flask:
FastAPI:
可以看到,同样的四次请求,Flask先是阻塞了40秒,然后依次返回结果,FastAPI则是第一次阻塞后直接返回,这代表了在FastAPI中阻塞了一个事件队列,证明FastAPI是异步框架,而在Flask中,请求可能是在新线程中运行的。将所有CPU绑定的任务移到单独的进程中,所以在FastAPI的例子中,只是在事件循环中sleep(所以异步框架这里最好不要使用time.sleep而是asyncio.sleep)。在FastAPI中,异步运行IO绑定的任务。
当然这不能说明太多问题,我们继续使用鼎鼎有名的ApacheBench分别对两款框架进行压测。
一共设置5000个请求,QPS是100(请原谅我的机器比较渣)。 ab -n 5000 -c 100 http://127.0.0.1:5000/ ab -n 5000 -c 100 http://127.0.0.1:8000/
这里为了公平起见,Flask配合Gunicorn服务器,开3个worker,FastAPI配合Uvicorn服务器,同样开3个worker。
Flask压测结果: liuyue:mytornado liuyue$ ab -n 5000 -c 100 http://127.0.0.1:5000/ This is ApacheBench, Version 2.3 <$Revision: 1826891 gt; Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 127.0.0.1 (be patient) Completed 500 requests Completed 1000 requests Completed 1500 requests Completed 2000 requests Completed 2500 requests Completed 3000 requests Completed 3500 requests Completed 4000 requests Completed 4500 requests Completed 5000 requests Finished 5000 requests Server Software: gunicorn/20.0.4 Server Hostname: 127.0.0.1 Server Port: 5000 Document Path: / Document Length: 28 bytes Concurrency Level: 100 Time taken for tests: 4.681 seconds Complete requests: 5000 Failed requests: 0 Total transferred: 1060000 bytes HTML transferred: 140000 bytes Requests per second: 1068.04 [#/sec] (mean) Time per request: 93.629 [ms] (mean) Time per request: 0.936 [ms] (mean, across all concurrent requests) Transfer rate: 221.12 [Kbytes/sec] received
FastAPI压测结果: liuyue:mytornado liuyue$ ab -n 5000 -c 100 http://127.0.0.1:8000/ This is ApacheBench, Version 2.3 <$Revision: 1826891 gt; Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 127.0.0.1 (be patient) Completed 500 requests Completed 1000 requests Completed 1500 requests Completed 2000 requests Completed 2500 requests Completed 3000 requests Completed 3500 requests Completed 4000 requests Completed 4500 requests Completed 5000 requests Finished 5000 requests Server Software: uvicorn Server Hostname: 127.0.0.1 Server Port: 8000 Document Path: / Document Length: 19 bytes Concurrency Level: 100 Time taken for tests: 2.060 seconds Complete requests: 5000 Failed requests: 0 Total transferred: 720000 bytes HTML transferred: 95000 bytes Requests per second: 2426.78 [#/sec] (mean) Time per request: 41.207 [ms] (mean) Time per request: 0.412 [ms] (mean, across all concurrent requests) Transfer rate: 341.27 [Kbytes/sec] received
显而易见,5000个总请求,Flask花费4.681秒,每秒可以处理1068.04个请求,而FastAPI花费2.060秒,每秒可以处理2426.78个请求。
结语:曾几何时,当人们谈论Python框架的性能时,总是不自觉的嗤之以鼻 ,而现在,Python异步生态正在发生着惊天动地的变化,新的框架应运而生(Sanic、FastAPI),旧的框架正在重构(Django3.0),很多库也开始支持异步(httpx、Sqlalchemy、Mortor)。软件科技发展的历史表明,一项新技术的出现和应用,常常会给这个领域带来深刻的变革,古语有云:察势者智,顺势者赢,驭势者独步天下。所以,只有拥抱未来、拥抱新技术、顺应时代才是正确的、可持续发展的道路。
三星GalaxyS23系列系统占用空间惊人,高达60GBIT之家2月7日消息,据部分三星GalaxyS23系列机型用户反映,新机预装的Android13系统所占用的存储空间非常多,高达60GB,比Pixel7的大四倍。作为参考,Pixe
三星Exynos2400规格泄露十核心,配备X4超大核2月6日消息,在近期,有消息称三星旗下的Exynos2400已经完成了内部审查,即将量产阶段,预期在2023年11月进入量产阶段。博主i冰宇宙则对三星旗下的Exynos2400进行
WiFi7有何优势?雷军更大更快更强小米在今天带来了一则重磅消息,小米13Pro和K60Pro以及自家的万兆路由器都将会升级全新一代WiFi7标准,为用户带来更高速率更稳连接更低功耗的网络体验,那么WiFi7对比现在
用加倍努力弥补遗憾原标题用加倍努力弥补遗憾我们应学会放下遗憾,加倍努力做得更好,弥补遗憾现实中,许多人总想把事情做得尽善尽美,有一种完美期待。这虽是好事,但不能因为追求完美而背上精神包袱。其实,留有
老人讲真实民间故事据说古代李太清是一个有才的进士,深受皇帝喜爱。有一次,皇帝派他到湖广为御花园办些奇花异草假山怪石,顺便让他回乡探亲。李太清领了好多银子,行了好多路程,来到乡里,见到洪水冲毁良田,听
CBA三消息NBL数据王引关注,CBA第一大外闲置,曾凡博创造历史NBL常规赛收官,陕西信达队中锋杨文学赛季场均25。5分14。1篮板2盖帽,包揽得分王篮板王盖帽王,帮助球队取得头名。这名宁夏的球员,身高2。06左右,今年24岁正是上升期,因为杨
广东廉江楼市的危机,为何廉江房价如此之低,廉江市楼市的潜力广东省最发达的地方主要集中在珠三角的几个城市,其中深圳和广州的房价在全国处于前5位。另外东莞佛山等地的房价也不便宜,应该说位于珠三角区域城市,房价基本也突破万元或者接近万元,但远离
赛季已近尾声山西女篮努力创作完美结局山西女篮主帅塞萨在布置战术。希望在这个赛季结束后,球队能够写出一本好书。山西女篮主帅塞萨如是说。2月2日,山西竹叶青酒女篮举行媒体开放日活动。即将出战WCBA联赛的女篮展示了体能恢
10次单月常规赛场均3010!字母哥追平NBA历史纪录尽管在很多人的心目中本赛季NBA常规赛MVP之争成为了约基奇和塔图姆的对决,但是我们不能忽视的是字母哥仍有漂亮的个人数据,且带领伤病不断的雄鹿打出了不错的战绩。在打完2023年1月
明日加冕?历史得分王皇冠明日易主?明日(北京时间2月5日),湖人将在前往新奥尔良球馆,客场挑战鹈鹕,力争三连胜。赛季至今,湖人25胜28负,暂列西部第12而鹈鹕因主力伤病问题,遭遇一波十连败后,西部排名持续下降,目
宏兔大展春眠不觉兔,处处闻啼鸟云衡微语春天的梦想一年之计在于春。今天就是四季里第一个节气,也是进入兔年大年生活的结束之时,面对大年的尾声,立春的开始,我们同心集合,昂首阔步地向着春天般的兔年挺进!三年的疫情,耽