具有龙卷风Python的简单异步服务器

时间:2016-10-31 22:31:20

标签: python asynchronous tornado

我想用Tornado编写一个简单的异步http服务器。 我不清楚如何设置回调以便在处理当前请求时释放服务器以获取其他请求。

我写的代码是:

import tornado.web
from tornado.ioloop import IOLoop
from tornado import gen
import time

class TestHandler(tornado.web.RequestHandler):
    @gen.coroutine
    def post(self, *args, **kwargs):
        json_input = tornado.escape.json_decode(self.request.body)
        print ('Now in POST. body: {}'.format(json_input))
        self.perform_long_task(*args, **json_input)

    @gen.coroutine
    def perform_long_task(self, **params):
        time.sleep(10)
        self.write(str(params))
        self.finish()

application = tornado.web.Application([
    (r"/test", TestHandler),
    ])

application.listen(9999)
IOLoop.instance().start()

为了测试我试图并行发送几个POST请求:

curl -v http://localhost:9999/test -X POST -H "Content-Type:appication/json" -d '{"key1": "val1", "key2": "val2"}' &

当处理perform_long_task()时,服务器被阻止。 我需要帮助使服务器成为非阻塞服务器。

2 个答案:

答案 0 :(得分:0)

永远不要在Tornado代码中使用time.sleep

http://www.tornadoweb.org/en/latest/faq.html#why-isn-t-this-example-with-time-sleep-running-in-parallel

请在代码中执行此操作:

class TestHandler(tornado.web.RequestHandler):
    @gen.coroutine
    def post(self, *args, **kwargs):
        json_input = tornado.escape.json_decode(self.request.body)
        print ('Now in POST. body: {}'.format(json_input))
        # NOTE: yield here
        yield self.perform_long_task(*args, **json_input)

    @gen.coroutine
    def perform_long_task(self, **params):
        yield gen.sleep(10)
        self.write(str(params))
        # NOTE: no need for self.finish()

你不需要打电话给self.finish - 当" post" coroutine完成后,Tornado会自动完成请求。

你必须得到self.perform_long_task(),否则Tornado会在你调用" self.write()"之前提前结束你的请求。

一旦你做出这些改变,两个" curl"命令将显示您正在Tornado中进行并发处理。

答案 1 :(得分:0)

  1. 我仍在使用time.sleep(),因为我的代码调用了其他无法控制编写方式的代码。
  2. 常见问题解答http://www.tornadoweb.org/en/latest/faq.html#why-isn-t-this-example-with-time-sleep-running-in-parallel介绍了三种方法。第三个是我需要的。
  3. 我的代码中唯一需要更改的是:     yield self.perform_long_task(* args,** json_input)
    它仅适用于为异步编写的类,

    使用:     yield executor.submit(self.perform_long_task,* args,** json_input)

    所有回复和评论都很有帮助。非常感谢!