My ThreadPoolExecutor / gen.coroutine (tornado v4.x) решение обойти блокировку веб-сервера больше не работает с торнадо версии 6.x.
Некоторое время назад я начал разрабатывать онлайн-браузерную игру, используявеб-сервер Tornado (v4.x) и веб-сокеты.Всякий раз, когда ожидается ввод данных пользователем, игра отправляет вопрос клиенту и ждет ответа.Тогда я использовал 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 создает dict со списком (выбором) и идентификатором и сохраняет его в плеерах self.callbacks.После этого он просто остается в цикле while, пока функция websocket.on_message не поместит полученный ответ (который выглядит следующим образом: id: Choice_id, например, 1: 12838732) в dict обратных вызовов.