Python常见Web框架性能对比(一)

首先:

  • 没有专用的服务器
  • 没有测试专用的代码片段
  • 没有牛人背书

这只是一个简单的对比: 用一台普通的机器,以尽量相同的方式分别部署不同Web框架编写的一段简单程序.然后使用压力测试程序run一下,做个chart出来.直观的反应一下. .python的常用框架性能之间的差别.较真的杠精现在就可以出门左转了.

先要介绍一下我的测试环境: acer的商务机,具体配置是酷睿8,8g,1t的5400转机械硬盘, 操作系统是ubuntu 18.04 desktop

本次使用的代码特别简单,所以因为个人能力不济造成性能下降的可能性比较小,哈哈.本次测试的是一些常用的python的Web开发框架.下面有请选手登场:

  • Django 不用说,最早进入中国的python web框架之一, 一站式结构, 文档齐全, 功能强大.用户众多,入坑首选之一
  • Flask 知名度和Django在伯仲之间的python web框架,和相对重型的Django不同,flask标榜自己的轻量级, 做个单纯的web框架,只负责路由和视图部分,其他的交给插件部分(flask众多的插件也是亮点之一).入坑首选之二
  • AioHttp 一个异步的web框架,包含服务端和客户端,推荐python 3.5+, 视图函数是异步写法.也是因为异步,所以性能出色.
  • Sanic 也是异步类flask的web框架,无需插件即支持websocket,因为是类flask框架,所以从flask 转过来的话无论学习还是维护成本都是极低的.性能自己说也是非常高的.在国外有大量的生产环境案例. 插件/中间件很丰富.
  • Tornado 是一个facebook开源的异步框架,自己的文档说速度相当快,国内也有很多人这么说,我不怕剧透,其实他的性能从4.2时代就已经很落伍了.而且由于他的异步机制是自己搞的一套.很多东西写法都很独特.学习成本较高.所以,本人是不推荐学习的.也没任何优势而已,这里把他拉出来就是为了衬托同行.
  • Bottle 一个超简洁的轻量级web框架.(5年之前)以性能著称.同步模式.国外国内都不算应用广.比flask更简洁,但是插件也比较少.
  • Falcon 这个国内用的不多,但是国外用户还是很多的.以安全稳定著称(就是所谓的线程安全那种,你懂的),自说是性能和安全的最佳平衡.有很多生产环境的案例.主要是用于提供接口服务. 语法稍微繁琐一点.
  • Vibora 一个很新的异步模式的类flask的web框架,flask开发者友好(要抢flask的饭碗?),性能也是变态的好.个人觉得不错.(毕竟类flask的框架,对插件的依赖是可有可无的)

很多人都知道Python语言的代码,以运行缓慢著称(我这是引用众数的观点.不抬杠),所以很多人诟病Python的web框架运行缓慢.不过,个人的观点是: 实务中, 特别当你不是那么大的分布式的部署的时候,性能瓶颈往往是压在数据库而不是web框架上.你可以根据自己的网站/业务的访问量计算一下你选中的Web框架是否能满足你的需求?

测试代码就是各自的文档中的hello world代码.部署上能用gunicorn的就用,有些部署比较特殊的框架那没办法,总是,尽量减少部署方式上的差异(python的web框架,部署方式对性能的影响还是非常大的).

测试方式使用siege做并发压力测试,从50客户端开始,每次测试递增50个客户端,一直到最后1000个客户端,每次5000个事务请求. 每个框架做400批次压力测试.最后的结果清洗后做个统计,使用pygal生成图表. x轴是客户端数量,y轴是每秒处理多少事务(TPS),所有的测试结果都是100%完成.

测试结果

Django

Django_bar.png

Flask

Flask_bar.png

Bottle

Bottle_bar.png

Falcon

Falcon_bar.png

从这里开始,都是异步的框架了

Tornado

Tornado_bar.png

Sanic

Sanic_bar.png

AioHttp

AioHttp_bar.png

Vibora

Vibora_bar.png

全家福

total_bar.png

个人总结:

  • 无论同步还是异步模式,所有的框架在低并发(50客户端以内)性能都是出奇的好.如果使用QPS的换算公式的话.你会发现,如果一般性类的网站(企业门户,个人博客之类),速度上完全没问题.
  • 并发能力上来说,Django和Flask难兄难弟日常垫底儿.但这并不影响他们的广泛应用.而且,即使是他们的垫底性能,也能在1000客户端的情况下维持每秒1000上下的TPS.坦白的说,这算不上高性能,但是满足绝大多数站点(尤其是创业初期的产品原型)的需求是没问题了.
  • 同步工作模式和异步工作模式相比,并发能力上全面落后挨打.甚至被秒杀.但是,异步工作模式在代码书写上是有要求的(有些coder常说的一步异步,处处异步并不是没有道理的).并且异步提升的是单位时间的处理能力.在你的服务器崩溃之前,异步工作模式并不会提供更高的处理能力.
  • Tornado 成也性能,败也性能.在异步的时代,tornado以较高学习成本,捉急的性能,让成为拍在沙滩上的前浪.至少现在.不要说tornado的性能高什么的了.
  • Vibora 性能确实变态. 即使1000客户端,也能维持超过1万的TPS.值得关注一下.

以上是空载的数据,如果加上本地的数据库负载(原子操作).所有的框架没有任何差别.瓶颈都在数据库IO上.

python的web框架多如牛毛(远不像国内的翻来覆去django,flask,tornado三大件).特点也是千差万别.基本上越新的框架越有后发的优势,我会在工作之余,做一些相关的对比工作.

代码片段(Hello World):

测试代码引自官方文档,未做任何优化.

Falcon
# -*- coding: utf-8 -*-
import falcon
from wsgiref import simple_server


app = falcon.API()


class ThingsResource(object):
    def on_get(self, req, resp):
        """Handles GET requests"""
        resp.status = falcon.HTTP_200  # This is the default status
        resp.body = ("Hello Falcon!")


things = ThingsResource()
app.add_route('/query/', things)


if __name__ == "__main__":
    httpd = simple_server.make_server('127.0.0.1', 8086, app)
    httpd.serve_forever()
AioHttp
# -*- coding: utf-8 -*-
from aiohttp import web


route = web.RouteTableDef()
app = web.Application()
port = 8084


@route.get('/query/')
async def hello_world(request):
    return web.Response(text="Hello, Aio!")


async def my_web_app():
    app = web.Application()
    app.add_routes(route)
    return app



if __name__ == '__main__':
    web.run_app(app=my_web_app(), host="0.0.0.0", port=port)
Bottle
# -*- coding: utf-8 -*-
from bottle import route, run, default_app


app = default_app()


@route('/query/')
def index():
    return "Hello Bottle!"


if __name__ == "__main__":
    run(app=app, host='0.0.0.0', port=8082, server="tornado")
Flask
# -*- coding: utf-8 -*-
from flask import Flask

app = Flask(__name__)


@app.route('/query/')
def hello_world():
    return 'Hello Flask!'


if __name__ == '__main__':
    app.run()
Sanic
# -*- coding: utf-8 -*-
from sanic import Sanic
from sanic import response


app = Sanic()


@app.route("/query/")
async def test(request):
    request
    return response.text("Hello Sanic!")

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8083, debug=True)
    pass
Tornado
# -*- coding: utf-8 -*-
import tornado.ioloop
import tornado.web
from tornado.httpserver import HTTPServer
from tornado import gen
from tornado.ioloop import IOLoop


class MainHandler(tornado.web.RequestHandler):
    @gen.coroutine
    def get(self):
        self.write("Hello, Tornado!")

def make_app():
    return tornado.web.Application([
        (r"/query/", MainHandler),
    ])


if __name__ == "__main__":
    app = make_app()
    server = HTTPServer(app)
    app.listen(8085)
    server.start(0)  # forks one process per cpu
    print("tornado server run on 8085....")
    IOLoop.current().start()

没有django的是因为django的代码太多,不方便贴. 有兴趣的自己去django手册看一下就好了.

写在最后

python的框架远远不止上面说的哪些, 可以说, 如果你想寻找一款最好的python开发框架,抱歉这个真没有.每个框架都有其存在的价值或者意义,尽管在某些方面看起来有些过时.和某些一两个框架独大的语言不同.python语言的框架是一种百花齐放百家争鸣的状态. 不过大体来说, python的web开发框架分2大类:

  • 全能型的一站式框架
  • 自助式的微框架

一站式框架

一站式框架提供了从路由,ctos,模板渲染,中间件, web-socket支持和orm等你想到的想不到的各种功能.有什么问题,看文档就行了. 语法的一致性好. 新需求导致的学习成本曲线平缓. 不太容易掉坑里. 一站式框架的典型代表是 Django.(发音类似: 姜戈,前面的d不发音)

微框架

微框架就是那种只提供基本功能的框架.在python中,这种提供单一功能的微框架忒多. 比如Flask仅仅提供了路由,蓝图之类的基本功能.(Flask模板还是借助jinja2来实现的,当然你也可以使用其他模板). 其他的功能,都需要你借助插件或者库来完成.比如说ORM方面,sqlalchemy, peewee, pony这些orm框架仅仅提供orm功能.你可以接触插件或者自己手工和web框架组合在一起工作. 当然和一站式框架相比,稍微多一些的学习成本.换来的是更多的选择甚至更高的性能.

  • 一站式就像管家一样,什么不会就问管家,除非管家说我也不会,那你就基本傻眼了.
  • 微框架就像个工具人. 而你是项目经理. 它负责做自己份内事.你的能力决定最终结果.
  • 一站式框架坑少. 选择入门初期提升快, 但中后期可能会遇到受框架设计思想约束的问题.
  • 微框架更开放一些, 有可能坑比较多,入门相对难一些. 但由于微框架对开发者的约束较少. 吃透了以后, 容易达到一种一通百通的状态(微框架的设计思维上基本都是想通的). 中后期在业务处理上会比较得心应手.相对的技术栈可以延伸的更广.

如何选择

django和flask是入门首选.他们共同的特点就是成熟稳定. 两者都已经在生产环境经受过大量考验.性能虽然平庸,但稳如老狗. 业务上基本上是百搭型. github上两者都是51K+的星.根据个人喜爱可以二选一. 2者之间的差别主要是来源于自身的设计思维:

如果你打算长期从事python开发工作,我推荐你用微框架的一站式入门. 虽然开始会多一些磕磕绊绊,但你后来的道路会走的更宽敞. 如果你只是python的web框架轻度用户.无疑学习django见效更快. 当然,你的性格也会影响选择: django的开发者,需要遵守的约定更多一些. 性格上守序一点会比较好(会java的人会有是曾相识的感觉).flask的开发者需要遵守的约定比较少. 语法上也是更贴近于python提倡的简洁直白的风格 . 崇尚真我风格的年轻人可能更容易接受一些.

工作上是框架跟着业务走, 你不能先选择一个框架,让后让业务向框架的技术特点妥协.而是根据当前业务选择最适合的开发框架. 业务的需求是动态变化的.如果你当前的框架满足不了业务发展的需要, 那就选择一个能满足的业务需要的框架和当前的框架配合是使用. 因为你不能期望总有一个框架你满足你的业务发展中的所有需求.微框架因为其低耦合的特性.更容易迎合业务的变化. 这也是我推荐选择flask这种类型的微框架作为入门的原因之一.

你可能感兴趣的:(Python常见Web框架性能对比(一))