tornado是另一个基于python的服务器框架,虽然不能向django一样给我们提供丰富的“建站工具”,不过它对epoll的支持使得非阻塞特性比较吸引人。下面也简单记录一下安装使用方法。
首先下载安装tornado,运行它还需要安装下面两个库
1,pycurl
(python setup.py install)
tornado没有提供django的manage.py,django-admin.py等工具,直接编码如下
list_publishers.html(模板)
<table>
{% for p in publishers %}
<tr>
<td>Id #{{ p[0] }}</td>
<td>Name #{{ p[1] }}</td>
</tr>
{% end %}
</table>
web.py(代码)
import tornado.ioloop
import tornado.web
import tornado.database
import sqlite3
def _execute(query):
dbPath = '/home/ciaos/django.sqlite3'
connection = sqlite3.connect(dbPath)
cursorobj = connection.cursor()
try:
cursorobj.execute(query)
result = cursorobj.fetchall()
connection.commit()
except Exception:
raise
connection.close()
return result
class Main(tornado.web.RequestHandler):
def get(self):
self.write("Main")
class ListPublishers(tornado.web.RequestHandler):
def get(self):
query = ''' select * from books_publisher '''
publishers = _execute(query)
self.render("list_publishers.html", publishers=publishers)
application = tornado.web.Application([
(r"/", Main),
(r"/publishers" , ListPublishers),
],debug=True)
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
简单用ab测试一下性能,要比django性能高出一倍的样子(不过鉴于两个项目操作数据库的方式有些不一样,还是没有说服力,原因在于没能找到tornado对sqlite的原生支持)
ciaos@linux-53dr:~/mysite2> sudo /usr/sbin/ab2 -c 10 -n 10000 http://127.0.0.1:8888/publishers root's password: This is ApacheBench, Version 2.3 <$Revision: 655654 $> 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 1000 requests Completed 2000 requests Completed 3000 requests Completed 4000 requests Completed 5000 requests Completed 6000 requests Completed 7000 requests Completed 8000 requests Completed 9000 requests Completed 10000 requests Finished 10000 requests Server Software: TornadoServer/2.0 Server Hostname: 127.0.0.1 Server Port: 8888 Document Path: /publishers Document Length: 63 bytes Concurrency Level: 10 Time taken for tests: 21.306 seconds Complete requests: 10000 Failed requests: 0 Write errors: 0 Total transferred: 2190000 bytes HTML transferred: 630000 bytes Requests per second: 469.35 [#/sec] (mean) Time per request: 21.306 [ms] (mean) Time per request: 2.131 [ms] (mean, across all concurrent requests) Transfer rate: 100.38 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.2 0 7 Processing: 4 21 3.4 20 53 Waiting: 0 20 3.4 19 52 Total: 7 21 3.5 20 56 Percentage of the requests served within a certain time (ms) 50% 20 66% 21 75% 21 80% 22 90% 23 95% 25 98% 30 99% 42 100% 56 (longest request)生产环境的配置可以参照 Tornado概览 的介绍
user nginx; worker_processes 1; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { worker_connections 1024; use epoll; } http { # Enumerate all the Tornado servers here upstream frontends { server 127.0.0.1:8888; server 127.0.0.1:8000; } include /etc/nginx/mime.types; default_type application/octet-stream; access_log /var/log/nginx/access.log; keepalive_timeout 65; proxy_read_timeout 200; sendfile on; tcp_nopush on; tcp_nodelay on; gzip on; gzip_min_length 1000; gzip_proxied any; gzip_types text/plain text/html text/css text/xml application/x-javascript application/xml application/atom+xml text/javascript; # Only retry if there was a communication error, not a timeout # on the Tornado server (to avoid propagating "queries of death" # to all frontends) proxy_next_upstream error; server { listen 80; # Allow file uploads client_max_body_size 50M; location ^~ /static/ { root /var/www; if ($query_string) { expires max; } } location = /favicon.ico { rewrite (.*) /static/favicon.ico; } location = /robots.txt { rewrite (.*) /static/robots.txt; } location / { proxy_pass_header Server; proxy_set_header Host $http_host; #proxy_redirect false; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_pass http://frontends; } } }
简单的配置,就让我们可以远离老掉牙的php-cgi编程了。简单的mvc代码见附件