樱桃是如何工作的?当并发比较低时,与龙卷风相比,它可以很好地处理请求

use*_*075 7 python webserver asynchronous tornado cherrypy

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

我有三个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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

龙卷风异步

  siege ip -c20 -t100s             server can handle 3022requests  
  siege ip -c200 -t30s             server can handle 2259requests
  siege ip -c500 -t30s             server can handle 471requests
Run Code Online (Sandbox Code Playgroud)

绩效分析:

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

问题1:

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

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

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

问题2:

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

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()
Run Code Online (Sandbox Code Playgroud)

龙卷风同步:

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()
Run Code Online (Sandbox Code Playgroud)

龙卷风异步:

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()
Run Code Online (Sandbox Code Playgroud)

Rod*_*yde 2

回答问题1...

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

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

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