在ThreadPoolExecutor上运行游戏的Tornado 4.x解决方案不再起作用。需要帮助重构它

时间:2019-04-04 08:10:22

标签: python tornado

我的ThreadPoolExecutor / gen.coroutine(tornado v4.x)解决方案,用于阻止Web服务器,在龙卷风6.x版中不再起作用。

前一段时间,我开始使用Tornado网络服务器(v4.x)和websocket开发在线浏览器游戏。每当需要用户输入时,游戏就会将问题发送给客户端并等待响应。早于我使用gen.coroutine和ThreadPoolExecutor使该任务成为非阻塞。现在,我开始重构游戏,该游戏无法在Tornado v6.x上运行,并且任务再次阻止了服务器。我搜索了可能的解决方案,但到目前为止,我一直无法使其正常运行。我不清楚如何将现有代码再次更改为非阻塞。

server.py:

class PlayerWebSocket(tornado.websocket.WebSocketHandler):
    executor = ThreadPoolExecutor(max_workers=15)
    @run_on_executor
    def on_message(self,message):
        params = message.split(':')
        self.player.callbacks[int(params[0])]=params[1]

if __name__ == '__main__':
    application = Application()
    application.listen(9999)
    tornado.ioloop.IOLoop.instance().start()

player.py:

@gen.coroutine
def send(self, message):
   self.socket.write_message(message)

def create_choice(self, id, choices):
    d = {}
    d['id'] = id
    d['choices']=choices
    self.choice[d['id']]=d
    self.send('update',self)
    while not d['id'] in self.callbacks:
        pass
    del self.choice[d['id']]
    return self.callbacks[d['id']]

无论何时做出选择,create_choice函数都会创建一个带有列表(选择)和ID的字典并将其存储在玩家self.callbacks中。之后,它将一直停留在while循环中,直到websocket.on_message函数将接收到的答案(如下所示:id:Choice_id,例如1:12838732)放入回调dict中。

1 个答案:

答案 0 :(得分:0)

WebSocketHandler.write_message方法不是线程安全的,因此只能从IOLoop的线程中调用,而不能从ThreadPoolExecutor中调用(这一直是对的,但有时似乎仍然可以工作)。

修复此代码的最简单方法是将IOLoop.current()保存在主线程的全局变量中(current()函数访问线程局部变量,因此您无法从线程中调用它池)并使用ioloop.add_callback(self.socket.write_message, message)(并从@gen.coroutine中删除send-如果不包含函数yield,则使协程成为无效)。