【问题标题】:tornado one handler blocks for another龙卷风一个处理程序阻塞另一个
【发布时间】:2016-06-16 02:53:28
【问题描述】:

我想使用 python/tornado 设置一个小型“蹦床”服务器,允许两个设备以 REST 方式相互通信。可能有更好/更简单的“现成”方法来做到这一点。我欢迎这些建议,但我仍然觉得弄清楚如何自己使用龙卷风是很有教育意义的。

基本上,我的想法是让设备扮演服务器角色,使用 GET 进行长轮询。客户端设备将 POST 到服务器,此时 POST 正文将作为被阻止的 GET 的响应传输。在 POST 响应之前,它会阻塞。然后服务器端对响应执行 PUT,该响应被传输到被阻止的 POST 并返回到设备。我也许我可以用 tornado.queues 做到这一点。但这似乎没有奏效。我的代码:

import tornado
import tornado.web
import tornado.httpserver
import tornado.queues

ToServerQueue = tornado.queues.Queue()
ToClientQueue = tornado.queues.Queue()

class Query(tornado.web.RequestHandler):
    def get(self):
        toServer = ToServerQueue.get()
        self.write(toServer)

    def post(self):
        toServer = self.request.body
        ToServerQueue.put(toServer)
        toClient = ToClientQueue.get()
        self.write(toClient)

    def put(self):
        ToClientQueue.put(self.request.body)
        self.write(bytes())

services = tornado.web.Application([(r'/query', Query)], debug=True)
services.listen(49009)
tornado.ioloop.IOLoop.instance().start()

不幸的是,ToServerQueue.get() 在队列有项目之前实际上并没有阻塞,而是返回一个 tornado.concurrent.Future。这不是传递给self.write() 调用的合法值。

我想我的一般问题是双重的:

1) 一个 HTTP 动词调用(例如 get、put、post 等)如何阻塞,然后由另一个 HTTP 动词调用发出信号。

2) 如何将数据从一个调用共享到另一个调用?

我只真正触及了使用 tornado 制作小型 REST 服务器的简单/直接用例。我想知道协程的东西是否是我需要的,但还没有找到一个好的教程/示例来帮助我看到光明,如果这确实是要走的路。

【问题讨论】:

    标签: python tornado


    【解决方案1】:

    1) 一个 HTTP 动词调用(例如 get、put、post、u ne 等)如何阻塞,然后由另一个 HTTP 动词调用发出信号。

    2) 如何将数据从一个调用共享到另一个调用?

    为每个请求创建新的RequestHandler 对象。所以你需要一些协调员,例如queueslocks 带有状态对象(在您的情况下,它将重新实现队列)。

    tornado.queues 是协程队列。 Queue.getQueue.putQueue.join 返回需要“解决”的未来对象 - 计划任务成功或异常完成。要等到未来解决,您应该yielded 它(就像在tornado.queues 的文档示例中一样)。动词方法也需要用tornado.gen.coroutine修饰。

    import tornado.gen
    
    class Query(tornado.web.RequestHandler):
    
        @tornado.gen.coroutine
        def get(self):
            toServer = yield ToServerQueue.get()
            self.write(toServer)
    
        @tornado.gen.coroutine
        def post(self):
            toServer = self.request.body
            yield ToServerQueue.put(toServer)
            toClient = yield ToClientQueue.get()
            self.write(toClient)
    
        @tornado.gen.coroutine
        def put(self):
            yield ToClientQueue.put(self.request.body)
            self.write(bytes())
    

    GET 请求将持续(以非阻塞方式等待)直到队列中有可用的内容(或超时,可定义为 Queue.get arg)。

    tornado.queues.Queue 还提供了不必产生的 get_nowait(还有 put_nowait) - 立即从队列中返回项目或抛出异常。

    【讨论】:

    • 我刚刚发现在 debian testing/stretch 上运行,这些都是可用的,因为它有 Tornado 4.3(队列显然是在 4.2 中引入的)。但它们在 debian stable/jessie 上不可用,其中 python3-tornado 软件包适用于 Tornado 3.2。旧版本的 Tornado 有简单的解决方案吗?还是我需要弄清楚如何让我的目标机器使用更高版本的 debian?
    • 有一个toro (toro.readthedocs.io/en/stable),实际上该库在tornado.queuetornado.locks 中合并到Tornado (4.x) :)
    猜你喜欢
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多