我有一个Tornado服务器,用于通过使用RabbitMQ后端向一些Celery工作人员提交任务来提交长时间运行(〜分钟)计算。提交的任务是在WebSocketHandler
:
class MainWSHandler(WebSocketHandler):
def open(self):
logging.info("Connection opened.")
def on_close(self):
logging.info("Connection closed.")
def on_message(self, message):
result = self.submit_task(message)
self.write_message("Calculation has been submitted")
@gen.coroutine
def submit_task(self, params):
result = yield gen.Task(long_calculation.apply_async, args=[params])
self.write_message("Completed calculation")
return result
如果用户永远不会离开具有当前打开的Web套接字的页面,则此方法很有效。如果他们这样做,并且Web套接字关闭,则返回的消息self.write_message("Completed calculation")
将失败并显示WebSocketClosedError
。如果用户不想再回到页面一段时间(即计算完成之后),这很好。
但是,如果用户提交计算,离开页面,然后在计算完成之前返回,则会引发相同的错误,因为Web套接字已关闭并且打开了新的套接字。这可以防止计算完成消息传播到前端。
我的问题是:是否可以重新连接到同一个Web套接字?或者,或者,如何确保计算完成后返回的消息使其进入用户的当前页面?
答案 0 :(得分:0)
似乎我可能已经跳过了枪,假设这个长期运行的任务与网络套接字系统固有的这个问题的结构解决方案。
将当前打开的Web套接字存储在类属性
中就足够了class MainWSHandler(WebSocketHandler):
self.clients = {}
def open(self):
logging.info("Connection opened.")
self.clients[self.current_user] = self
使用存储的Web套件处理任务的响应
@gen.coroutine
def submit_task(self, params):
result = yield gen.Task(long_calculation.apply_async, args=[params])
# Retrieve current web socket
ws = self.clients[self.current_user]
ws.write_message("Completed calculation")
return result
可能有更有效的方式(或一些惯用法),但我现在对此解决方案感到满意。