速度为先 当下,python都已经更新到了 Python3.9.3 了,如果你还没有使用过 asyncio、和 Python3.5 新增的 async/await 语法,那说明你可能真的是桃花源人,问今是何世,不知有汉,无论魏晋了。
在当下,基于 async/await 语法的异步 Web 框架也有很多,在 github 上找一找比比皆是是,那究竟应该选哪一款呢?在 github 上有一个专门测试各种语言各种 Web 框架速度的项目,我们来看一看简单的数据:
这是所有的 Python Web 框架速度测试,有人可能会问为什么不是从 1 开始排序的,因为这个项目的测试还包含 golang、java、php 等众多语言的 Web 框架,共有 226 款。这里我们只用 Python 来做对比。
可以明显的看到,flask、django、tornado 等老牌的 Python Web 框架已经快要垫底了。
wow, 这个速度绝了。可能你们还在怀疑这个速度如何测试的,给你们看一下测试源码:
# Disable all logging features import logging logging.disable()from flask import Flaskfrom meinheld import patch patch.patch_all() app = Flask(__name__)@app.route("/") def index () : return "" @app.route("/user/", methods=["GET"]) def user_info (id) : return str(id)@app.route("/user", methods=["POST"]) def user () : return "" 复制代码from django.http import HttpResponsefrom django.views.decorators.csrf import csrf_exemptdef index (request) : return HttpResponse(status=200 )def get_user (request, id) : return HttpResponse(id)@csrf_exempt def create_user (request) : return HttpResponse(status=200 ) 复制代码# Disable all logging features import logging logging.disable()import tornado.httpserverimport tornado.ioloopimport tornado.webclass MainHandler (tornado.web.RequestHandler) : def get (self) : pass class UserHandler (tornado.web.RequestHandler) : def post (self) : pass class UserInfoHandler (tornado.web.RequestHandler) : def get (self, id) : self.write(id) app = tornado.web.Application( handlers=[ (r"/" , MainHandler), (r"/user" , UserHandler), (r"/user/(\d+)" , UserInfoHandler), ] ) 复制代码# Disable all logging features import logging logging.disable()import multiprocessingfrom sanic import Sanicfrom sanic.response import text app = Sanic("benchmark" )@app.route("/") async def index (request) : return text("" )@app.route("/user/", methods=["GET"]) async def user_info (request, id) : return text(str(id))@app.route("/user", methods=["POST"]) async def user (request) : return text("" )if __name__ == "__main__" : workers = multiprocessing.cpu_count() app.run(host="0.0.0.0" , port=3000 , workers=workers, debug=False , access_log=False ) 复制代码
就是简单的不做任何操作,只返回响应,虽然这样测试没有任何实际意义,在正常的生产环境中不可能什么都不做,但是如果所有的框架都如此测试,也算是从一定程度上在同一起跑线上了吧。
OK,就这么多,说到这里你也应该知道我想要说的这个异步框架是谁了,没错,我们今天的主角就是 Sanic 。
为什么要用异步 Web 框架? 这可能是众多小伙伴最先想到的问题了吧?我用 Django、Flask 用的好好的,能够完成正常的任务,为什么还要用异步 Web 框架呢?
说到这里,首先我要反问你你一个问题,你认为在 Web 开发过程中我们最大的敌人是谁?思考 5 秒钟,然后看看我的回答:
在 Web 开发的过程中,我们最大的敌人不是用户,而是阻塞!
是的,而异步可以有效的解决 网络 I/O 阻塞,文件 I/O 阻塞。具体的阻塞相关的文章推荐查看深入理解 Python 异步编程。由于异步可以提升效率,所以对于 Python 来说,异步是最好的提升性能的方式之一。这也是为什么要选择 异步 Web 框架的原因。
生态环境 可能有的小伙伴还是会说,你为什么不推荐 falcon 而是推荐 Sanic ?明明它的速度非常快,要比 Sanic 快了那么多,那您看一下下面的代码:
from wsgiref.simple_server import make_serverimport falconclass ThingsResource : def on_get (self, req, resp) : """Handles GET requests""" resp.status = falcon.HTTP_200 # This is the default status resp.content_type = falcon.MEDIA_TEXT # Default is JSON, so override resp.text = ('\nTwo things awe me most, the starry sky ' 'above me and the moral law within me.\n' '\n' ' ~ Immanuel Kant\n\n' ) app = falcon.App() things = ThingsResource() app.add_route('/things' , things)if __name__ == '__main__' : with make_server('' , 8000 , app) as httpd: print('Serving on port 8000...' ) httpd.serve_forever()
一个状态码都要自己定义和填写的框架,我想它的速度快是值得肯定的,但是对于开发者来说,又有多少的实用价值呢?所以我们选择框架并不是要选最快的,而是要又快又好用的。
而大多数框架并不具备这样的生态环境,这应该也是为什么大多数 Python 的 Web 开发者愿意选择 Django 、 Flask 、 tornado 的原因。就是因为它们的生态相对于其他框架要丰富太多太多。
可是,如今不一样了。Sanic 框架, 从 2016 年 5 月开始 发布了第一版异步 Web 框架雏形,至今已经走过了 5 个年头,这 5 年,经过不断地技术积累,Sanic 已经由一个步履蹒跚的小框架变成了一个健步如飞的稳重框架。
在 awesome-sanic 项目中,记录了大量的第三方库,你可以找到任何常用的工具:从 API 到 Authentication,从 Development 到 Frontend,从 Monitoring 到 ORM,从 Caching 到 Queue… 只有你想不到的,没有它没有的第三方拓展。
生产环境 以前我在国内的社区中看到过一些小伙伴在问 2020 年了,Sanic 可以用于生产环境了吗?
答案是肯定的,笔者以亲身经历来作证,从19年底,我们就已经将 Sanic 用于生产环境了。彼时的 Sanic 还是 19.9,笔者经历了 Sanic 19.9 -- 21.3 所有的 Sanic 的版本,眼看着 Sanic 的生态环境变得越来越棒。