1. 程式人生 > >Flask, Tornado, GEvent組合執行與效能比較

Flask, Tornado, GEvent組合執行與效能比較

我在選一個python的網際網路框架, 本來已經定下來用Tornado了.  但我還聽到很多人推薦Flask的簡單性和靈活性, 還有gevent的高效能, 所以決定也試試它們以及它們和Tornado的結合.  我的示例就比”Hello World”應用稍微複雜一點兒, 它用到了模板.  下面是程式碼:

1, 純粹Flask (pure_flask.py)

from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def main_handler():
    return render_template('main_j2.html', messages="whatever",title="home")
if __name__ == '__main__':
    app.run(port=8888, debug=False)

2, 純粹Tornado (pure_tornado.py)

import os.path
import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.render('main.html', page_title="", body_id="", messages="whatever",title="home")

settings = {
    "static_path":os.path.join(os.path.dirname(__file__),'static'),
    "template_path":"templates",
}
application = tornado.web.Application([
    (r"/", MainHandler),
], **settings)

if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

3, Flask應用執行在Gevent上 (gevent_flask.py)

from gevent.wsgi import WSGIServer
from pure_flask import app
http_server = WSGIServer(('', 8888), app)
http_server.serve_forever()

4, Flask應用執行在Tornado上 (tornado_flask.py)

from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from pure_flask import app
http_server = HTTPServer(WSGIContainer(app))
http_server.listen(8888)
IOLoop.instance().start()

5, Tornado應用執行在Gevent上 (gevent_tornado.py)

import tornado.wsgi
import gevent.wsgi
import pure_tornado

application = tornado.wsgi.WSGIApplication([
    (r"/", pure_tornado.MainHandler),
],**pure_tornado.settings)

if __name__ == "__main__":
    server = gevent.wsgi.WSGIServer(('', 8888), application)
    server.serve_forever()

程式用到了三個模板檔案: main.html, layout.html, and form.html. 主程式只調用了main.html.  main.html擴充套件(“extends”)了 layout.html, 幷包含(“include”)了 form.html. 三個模板檔案加起來有30kB大小.

Flask和Tornado用了不同的模板檔案(Tornado是main.html, Flask是main_j2.html), 這是因為Flask和Tornado的模板語法雖然相似, 但有些地方不一樣.  比如Flask(用Jinja2)模板的”block”用”{% endblock %}”表示結束, “for”用”{% endfor %}”; 但是Tornado模板則只用”{% end %}”.

我用ApacheBench測了這五個的requests per second:

ab -n 1000 -c 4 http://localhost:8888/

每個測五次. 我的機型是6年老的雙核Opteron 254伺服器.

下面是結果:

pure_flask: 82 88 107 102 71
pure_tornado: 144 244 241 294 290
gevent_flask: 127 139 145 152 110
tornado_flask: 110 88 74 92 101
gevent_tornado: 328 555 177 273 153

五次平均:

pure_flask: 90
pure_tornado: 242
gevent_flask: 135
tornado_flask: 93
gevent_tornado: 297

從上面結果可能看出Tornado比Flask快很多. 而Gevent可以讓Tornado更快一些, 但快不了很多.

最終我還是喜歡Tornado應用的簡單明瞭, 用Flask寫稍微大一點的應用比較繁瑣(比如要使用藍圖-blueprints等), 所以還是決定使用Tornado了.