7

我对cherrypy(使用web.py作为框架)和tornado从互联网上检索网页进行了测试。

我有三个测试用例siege用于向服务器发送请求(-c 表示用户数;-t 是测试时间)。代码在测试结果下方。

1. web.py (cherrpy)

  siege ip -c20 -t100s             server can handle 2747requests  
  siege ip -c200 -t30s             server can handle 1361requests
  siege ip -c500 -t30s             server can handle 170requests

2.龙卷风同步

  siege ip -c20 -t100s             server can handle 600requests  
  siege ip -c200 -t30s             server can handle 200requests
  siege ip -c500 -t30s             server can handle 116requests

3. 龙卷风异步

  siege ip -c20 -t100s             server can handle 3022requests  
  siege ip -c200 -t30s             server can handle 2259requests
  siege ip -c500 -t30s             server can handle 471requests

性能分析:

tornado 同步 < web.py (cherrypy) < tornado 异步

问题一:

我知道,使用异步架构可以显着提高 Web 服务器的性能。

我很好奇 tornado 异步架构和 web.py (cherry) 之间的区别。

我认为龙卷风同步模式会一一处理请求,但是cherrypy是如何工作的,使用多个线程呢?但是我没有看到内存有很大的增加。Cherrypy 可能会同时处理多个请求。它是如何解决程序阻塞的?

问题2:

我可以在不使用异步技术的情况下提高 tornado 同步模式的性能吗?我认为龙卷风可以做得更好。

Web.py 代码:

import web
import tornado.httpclient
urls = (
    '/(.*)', 'hello'
)
app = web.application(urls, globals())

class hello:
    def GET(self, name):
        client = tornado.httpclient.HTTPClient()
        response=client.fetch("http://www.baidu.com/")
        return response.body

if __name__ == "__main__":
    app.run()

龙卷风同步:

import tornado.ioloop
import tornado.options
import tornado.web
import tornado.httpclient
from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)
class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        client = tornado.httpclient.HTTPClient()
        response = client.fetch("http://www.baidu.com/" )
        self.write(response.body)


if __name__=='__main__':
    tornado.options.parse_command_line()
    app=tornado.web.Application(handlers=[(r'/',IndexHandler)])
    http_server=tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

龙卷风异步:

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.httpclient
from tornado.options import define, options
define("port", default=8001, help="run on the given port", type=int)
class IndexHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self):
        client = tornado.httpclient.AsyncHTTPClient()
        response = client.fetch("http://www.baidu.com/" ,callback=self.on_response)

    def on_response(self,response):
        self.write(response.body)
        self.finish()

if __name__=='__main__':
    tornado.options.parse_command_line()
    app=tornado.web.Application(handlers=[(r'/',IndexHandler)])
    http_server=tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()
4

2 回答 2

2

要回答问题 1...

Tornado 是单线程的。如果您阻塞主线程,就像您在同步示例中所做的那样,那么在阻塞调用返回之前,该单个线程无法执行任何操作。这将同步示例限制为一次一个请求。

我对 web.py 不是特别熟悉,但是查看其 HTTP 服务器的源代码,它似乎使用了线程混合,这表明它不限于一次处理一个请求。当第一个请求进来时,它由一个线程处理。该线程将阻塞,直到 HTTP 客户端调用返回,但其他线程可以自由处理进一步的传入请求。这允许一次处理更多请求。

我怀疑如果您使用 Tornado 来模拟这一点,例如,通过将 HTTP 客户端请求传递给线程池,那么您会看到类似的吞吐量。

于 2012-12-04T10:56:07.120 回答
0

到目前为止,测试代码中的大部分处理程序时间都花在了client.fetch(...)- 有效地等待连接和套接字上的传入数据 - 而不会阻塞潜在的其他 Python 线程。

因此,您的“性能度量”主要取决于相关框架的有效处理程序线程的最大数量以及“百度”服务器允许从您的 IP 获得的最大并行连接数。

CherryPyWSGIServer web.wsgiserver.CherryPyWSGIServer默认情况下使用的wep.py 的副本web.httpserver.runsimple()确实使用线程 - 默认情况下为 10。
线程在这里不会增加内存使用量。大多数内存都由库和 Python 解释器本身消耗。而CherryPyWSGIServer的(10)处理工作线程都是从头开始的。替代的 web.httpserver.runbasic() 也使用线程——通过 Python 的内置 HTTPServer 和SocketServer.ThreadingMixIn. 这个为每个请求启动一个新线程。可能“无限”数量的线程 - 但每个请求的线程启动都有开销。

tornado异步模式也可能使用更多/无限数量的线程(?),这可以解释此处与 web.py 的区别。

您的测试并没有说明服务器和处理程序框架本身的执行速度。您可以简单地增加 web.py 的 CherryPyWSGIServer 中的最大线程数。以某种方式需要并行执行你client.fetch(...)的 's 以获得更多的“性能”。

要测试单纯的服务器/框架速度(开销成本),只需返回字符串或数据库查询或从本地内容呈现的典型完整网页。

一个进程中基于多线程 CPython 的 web&app 服务器最终不能使用超过一个 CPU 内核(今天在服务器硬件上通常可能有 8 个 CPU 内核)——因为 CPython 中的 GIL 仅针对某些 I/O 发布。因此,如果 CPU 负载成为一个因素(而不是网络或数据库速度),则可以考虑使用 Jython 或多进程方法。

于 2017-04-04T09:58:53.467 回答