tornado 异步web

若想学会异步,必先学同步。

1.同步web开发代码,就是单向进行的,服务器必须先响应前一个请求,才能处理后一个请求。

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.httpclient
import datetime

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):
        query = self.get_argument('q')
        client = tornado.httpclient.HTTPClient()
        response = client.fetch("http://www.baidu.com?wd={}".format(query))
        body = response.body
        result_count = len(body)
        now = datetime.datetime.utcnow()#输出的是代表世界时间
        self.write("""
            <div style="text-align: center">
                <div style="font-size: 72px">%s</div>
                <div style="font-size: 144px">%s</div>
                <div style="font-size: 144px">%s</div>
                <div style="font-size: 24px">tweets per second</div>
            </div>""" % (query,result_count, now))
        
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()

在linux终端运行优秀的Siege utility工具进行测试。它可以这样使用:

siege http://localhost:8000/?q=pants -c10 -t10s
 运行结果是:

2 异步web代码如下:

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.httpclient
import datetime

from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)

class IndexHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self):
        query = self.get_argument('q')
        client = tornado.httpclient.AsyncHTTPClient()
        client.fetch("http://www.baidu.com?wd={}".format(query), callback=self.on_response)

    def on_response(self, response):
        body = response.body
        result_count = len(body)
        now = datetime.datetime.utcnow()
        self.write("""
            <div style="text-align: center">
                <div style="font-size: 72px">%s</div>
                <div style="font-size: 144px">%s</div>
                <div style="font-size: 24px">%s</div>
                <div style="font-size: 24px">tweets per second</div>
            </div>""" % (self.get_argument('q'), result_count, now))
        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()

在linux终端运行优秀的Siege utility工具进行测试。它可以这样使用:

siege http://localhost:8000/?q=pants -c10 -t10s

 运行结果是:

 明显发现,在异步web 的response time的响应时间短,且successful transaction 次数多。因此异步的优势明显强于同步。记住当你使用@tornado.web.asynchonous装饰器时,Tornado永远不会自己关闭连接。你必须在你的RequestHandler对象中调用finish方法来显式地告诉Tornado关闭连接。异步相比较同步使用了callback回调函数,创建了client实例。callback函可不用等待上个任务结束,也可以运行。

3 异步web 简化版

mport tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.httpclient
import tornado.gen

import datetime

from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)


class IndexHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    @tornado.gen.engine
    def get(self):
        query = self.get_argument('q')
        client = tornado.httpclient.AsyncHTTPClient()
        response = yield tornado.gen.Task(client.fetch, "http://www.baidu.com?wd={}".format(query))
        body = response.body
        result_count = len(body)
        now = datetime.datetime.utcnow()
        self.write("""
            <div style="text-align: center">
                <div style="font-size: 24px">%s</div>
                <div style="font-size: 24px">%s</div>
                <div style="font-size: 24px">%s</div>
                <div style="font-size: 24px">tweets per second</div>
            </div>""" % (query, result_count, now))
        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()

 在linux终端运行优秀的Siege utility工具进行测试。它可以这样使用:

siege http://localhost:8000/?q=pants -c10 -t10s

 运行结果如下图:

Python的yield关键字以及tornado.gen.Task对象的一个实例,将我们想要的调用和传给该调用函数的参数传递给那个函数。这里,yield的使用返回程序对Tornado的控制,允许在HTTP请求进行中执行其他任务。此种异步没有调用callback函数。 程序相对第二种web异步简单。

猜你喜欢

转载自blog.csdn.net/weixin_42528089/article/details/83211641
今日推荐