Python的tornado框架性能研究

来源:互联网 发布:国税申报软件服务费 编辑:程序博客网 时间:2024/05/18 01:55

Python的tornado框架性能研究

  • Summary
  • 测试环境
    • 1 软硬件环境
    • 2 关于ab
    • 3 测试代码
  • Tornado性能考察
    • 1 Hello World
      • 11 1000个客户端总共请求1000次
      • 12 2000个客户端总共请求2000次
      • 13 2000个客户端总共请求20000次模拟用于通过浏览器访问网站
    • 2 连接保持很长的时间

1. Summary

  Tornado框架算是Python Web框架中比较有名的一个。以前一直没空研究,最近因为要做个项目,干脆深入考察一下tornado的性能。

2. 测试环境

2.1 软硬件环境

key value CPU【腾讯云VPS虚拟机】 8 核心 Intel(R) Xeon(R) CPU E5-26xx v3 内存 8GB 硬盘 100GB 操作系统 Ubuntu Server 16.04LTS 64bit python 2.7.12 64bit tornado 4.4.2 pycurl 7.43.0 nginx 1.10.0 ab【包含在apache2-utils里的一个压测命令】 2.3

2.2 关于ab

考虑到我们即将要压测,而现在Linux系统大多都有并发连接数限制,所以我们必须要做下面几件事

  1. 执行以下命令,使得Linux下单进程可以打开的文件句柄数大于1024
    ulimit -u 40960
  2. 编辑/etc/sysctl.conf文件
    设置net.ipv4.tcp_syncookies = 0

2.3 测试代码

# -.- coding:utf-8 -.-import platformimport tornado.ioloopimport tornado.webimport tornado.genimport tornado.optionsimport selectimport tornado.httpserverimport tornado.httpclientimport tornado.concurrent__author__ = 'chenjm'class BlockHandler(tornado.web.RequestHandler):    @tornado.web.asynchronous  # 重要!这个装饰器使得当前请求变成长连接,直到调用self.finish()为止    @tornado.gen.coroutine  # 重要! tornado的重要装饰器,使得当前请求可以用yield异步执行IO操作    def get(self):        yield tornado.gen.sleep(3)  # 模拟长达3秒的IO操作,但是不阻塞主线程        self.write("i sleep 3s\n")        self.finish()  # 结束本次连接class AsyncBlockHandler(tornado.web.RequestHandler):    @tornado.web.asynchronous    @tornado.gen.coroutine    def get(self, *args, **kwargs):        http_client = tornado.httpclient.AsyncHTTPClient()  # tornado异步客户端        http_req = tornado.httpclient.HTTPRequest(            url='http://127.0.0.1:8000/block',            method='GET',            validate_cert=False,            request_timeout=30)        response = yield tornado.gen.Task(http_client.fetch, http_req)  # 执行异步HTTP请求        if response.code == 200:            self.write(response.body)        else:            print "error code = ", response.code        self.finish()class TestHandler(tornado.web.RequestHandler):    @tornado.web.asynchronous    @tornado.gen.coroutine    def get(self, *args, **kwargs):        self.write("Hello Word")        self.finish()class Application(tornado.web.Application):    def __init__(self):        handlers = [            ('/block', BlockHandler),            ('/async_block', AsyncBlockHandler),            ('/test', TestHandler),        ]        super(Application, self).__init__(handlers)if __name__ == "__main__":    # tornado框架可以解析命令行参数,如果有这一句话,那么就可以传入--port=XX参数来指定socket绑定端口    tornado.options.define("port", default=8000, help="run on the given port", type=int)     # 分析命令行    tornado.options.parse_command_line()    # 生成http服务器对象    http_server = tornado.httpserver.HTTPServer(Application())    print u"Current System:", platform.system()    # 可以看看是否启用了epoll(仅对Linux系统有效)    print "epoll enabled : ", hasattr(select, "epoll")    # 如果不写这句话,那么tornado会使用默认的异步HTTP客户端,作者测试过,性能比较低。    # 所以最好按照官方文档给出的做法,使用基于libcurl的客户端框架,但是前提是安装pycurl    tornado.httpclient.AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient")    # tornado默认异步客户端最大并发是10,所以要把这个开大点,否则影响并发    # 注意!如果你启用了上述libcurl客户端,那么这句话一定要写在后面    tornado.httpclient.AsyncHTTPClient.configure(None, max_clients=20000)    # 侦听socket端口    http_server.listen(tornado.options.options.port)    # 启动事件循环    tornado.ioloop.IOLoop.current().start()

3. Tornado性能考察

3.1 Hello World!

我们先来测试一下test接口

3.1.1 1000个客户端,总共请求1000次

执行命令:【注意:不带-k参数】

ab -c 1000 -n 1000 "http://127.0.0.1:8000/test"

结果:

Document Path:          /testDocument Length:        10 bytesConcurrency Level:      1000Time taken for tests:   0.954 secondsComplete requests:      1000Failed requests:        0Total transferred:      205000 bytesHTML transferred:       10000 bytesRequests per second:    1048.56 [#/sec] (mean)Time per request:       953.685 [ms] (mean)Time per request:       0.954 [ms] (mean, across all concurrent requests)Transfer rate:          209.92 [Kbytes/sec] receivedConnection Times (ms)              min  mean[+/-sd] median   maxConnect:        0    2   4.9      0      15Processing:     1  110  39.7    105     799Waiting:        1  110  39.7    105     799Total:         14  113  39.1    105     799Percentage of the requests served within a certain time (ms)  50%    105  66%    114  75%    118  80%    143  90%    146  95%    167  98%    182  99%    187 100%    799 (longest request)

我们发现,大部分请求在200ms之内都被处理完毕,tornado应付得轻轻松松

3.1.2 2000个客户端,总共请求2000次

执行命令:

ab -c 2000 -n 2000 "http://127.0.0.1:8000/test"

结果:

Document Path:          /testDocument Length:        10 bytesConcurrency Level:      2000Time taken for tests:   1.895 secondsComplete requests:      2000Failed requests:        0Total transferred:      410000 bytesHTML transferred:       20000 bytesRequests per second:    1055.60 [#/sec] (mean)Time per request:       1894.649 [ms] (mean)Time per request:       0.947 [ms] (mean, across all concurrent requests)Transfer rate:          211.33 [Kbytes/sec] receivedConnection Times (ms)              min  mean[+/-sd] median   maxConnect:        0   76 260.1      0    1001Processing:     1  164 180.8    105     888Waiting:        1  164 180.8    105     888Total:         21  240 429.3    105    1887Percentage of the requests served within a certain time (ms)  50%    105  66%    108  75%    125  80%    186  90%    260  95%   1814  98%   1861  99%   1875 100%   1887 (longest request)

我们发现90%的请求在260ms之内得到相应,但是“Requests per second”仍然维持在1000次左右,也许这是个瓶颈。

3.1.3 2000个客户端,总共请求20000次(模拟用于通过浏览器访问网站)

执行命令:【注意,这里带-k开关, 因为现在大多数浏览器都是keep_alive访问网站】

ab -c 2000 -n 20000 -k "http://127.0.0.1:8000/test"

结果:

Document Path:          /testDocument Length:        10 bytesConcurrency Level:      2000Time taken for tests:   13.474 secondsComplete requests:      20000Failed requests:        0Keep-Alive requests:    20000Total transferred:      4580000 bytesHTML transferred:       200000 bytesRequests per second:    1484.34 [#/sec] (mean)Time per request:       1347.402 [ms] (mean)Time per request:       0.674 [ms] (mean, across all concurrent requests)Transfer rate:          331.95 [Kbytes/sec] receivedConnection Times (ms)              min  mean[+/-sd] median   maxConnect:        0  110 773.9      0    7011Processing:     1  461 145.0    452     908Waiting:        1  461 145.0    452     908Total:         22  572 789.7    464    7919Percentage of the requests served within a certain time (ms)  50%    464  66%    559  75%    604  80%    610  90%    620  95%    625  98%   1547  99%   7286 100%   7919 (longest request)

我们发现95%的请求在625ms之内得到相应,“Requests per second”维持在1500次左右,此时有很多连接的“Connect”花了很长时间,这说明,Tornado针对“listen+accept”操作的速度趋向于饱和。

3.2 连接保持很长的时间

未完待续。。。
to be continued……

0 0
原创粉丝点击