Tornado blocking asynchronous requests

前端 未结 2 604
暗喜
暗喜 2020-12-13 07:26

Using Tornado, I have a Get request that takes a long time as it makes many requests to another web service and processes the data, could take minutes to fully complete. I

相关标签:
2条回答
  • 2020-12-13 08:11

    Here's a complete sample Tornado app that uses the Async HTTP client and the gen.Task module to make things simple.

    If you read more about gen.Task in the docs you'll see that you can actually dispatch multiple requests at the same time. This is using the core idea of Tornado where everything is no blocking and still maintaining a single process.

    Update: I've added a Thread handler to demonstrate how you could dispatch work into a second thread and receive the callback() when it's done.

    import os
    import threading
    import tornado.options
    import tornado.ioloop
    import tornado.httpserver
    import tornado.httpclient
    import tornado.web
    from tornado import gen
    from tornado.web import asynchronous
    
    tornado.options.define('port', type=int, default=9000, help='server port number (default: 9000)')
    tornado.options.define('debug', type=bool, default=False, help='run in debug mode with autoreload (default: False)')
    
    class Worker(threading.Thread):
       def __init__(self, callback=None, *args, **kwargs):
            super(Worker, self).__init__(*args, **kwargs)
            self.callback = callback
    
       def run(self):
            import time
            time.sleep(10)
            self.callback('DONE')
    
    class Application(tornado.web.Application):
        def __init__(self):
            handlers = [
                (r"/", IndexHandler),
                (r"/thread", ThreadHandler),
            ]
            settings = dict(
                static_path = os.path.join(os.path.dirname(__file__), "static"),
                template_path = os.path.join(os.path.dirname(__file__), "templates"),
                debug = tornado.options.options.debug,
            )
            tornado.web.Application.__init__(self, handlers, **settings)
    
    class IndexHandler(tornado.web.RequestHandler):
        client = tornado.httpclient.AsyncHTTPClient()
    
        @asynchronous
        @gen.engine
        def get(self):
            response = yield gen.Task(self.client.fetch, "http://google.com")
    
            self.finish("Google's homepage is %d bytes long" % len(response.body))
    
    class ThreadHandler(tornado.web.RequestHandler):
        @asynchronous
        def get(self):
            Worker(self.worker_done).start()
    
        def worker_done(self, value):
            self.finish(value)
    
    def main():
        tornado.options.parse_command_line()
        http_server = tornado.httpserver.HTTPServer(Application())
        http_server.listen(tornado.options.options.port)
        tornado.ioloop.IOLoop.instance().start()
    
    if __name__ == "__main__":
        main()
    
    0 讨论(0)
  • 2020-12-13 08:12

    koblas's solution is great. Here is an alternative that makes use of tornado.gen

    import tornado.ioloop
    import tornado.web
    import tornado.gen
    import tornado.concurrent
    import time
    from threading import Thread
    from functools import wraps
    
    def run_async(func):
      @wraps(func)
      def async_func(*args, **kwargs):
        func_hl = Thread(target = func, args = args, kwargs = kwargs)
        func_hl.start()
        return func_hl
    
      return async_func
    
    @run_async
    def sleeper(callback):
      i = 0
      while i <= 10:
        print i
        time.sleep(1)
        i += 1
      callback('DONE')
    
    
    class MainHandler(tornado.web.RequestHandler):
        @tornado.web.asynchronous
        @tornado.gen.coroutine
        def get(self):
            response = yield tornado.gen.Task(sleeper)
            self.write(response)
            self.finish()
    
    class OtherHandler(tornado.web.RequestHandler):
        def get(self):
            self.write('hello world')
            print 'in other'
            self.finish()
    
    0 讨论(0)
提交回复
热议问题