5

我想每个人都知道如何处理 django 中长时间运行的任务:使用 celery 并放松。但是,如果我想通过 aiohttp(或 tornado)获得 websockets 的好处怎么办?

假设我有一个非常受 CPU 限制的任务,可能需要几秒钟到多 (5-10) 分钟。在 websocket 循环中处理此任务并通知用户进度似乎是个好主意。没有 ajax 请求,对短任务的响应非常快。

async def websocket_handler(request):
    ws = web.WebSocketResponse()
    await ws.prepare(request)

    async for msg in ws:
        if msg.tp == aiohttp.MsgType.text:     
            answer_to_the_ultimate_question_of_life_the_universe_and_everything =\
                long_running_task(msg.data, NotificationHelper(ws))
            ws.send_str(json.dumps({
                'action': 'got-answer',
                'data': answer_to_the_ultimate_question_of_life_the_universe_and_everything,
            }))
    return ws

但另一方面,据我所知,以这种方式提供的受 CPU 限制的任务会阻塞整个线程。如果我有 10 个工人和 11 个客户想要使用应用程序,那么在第一个客户的任务完成之前,不会为第 11 个客户提供服务。

也许,我应该运行在 celery中看起来很大的任务和在主循环中看起来很小的任务?

所以,我的问题是:有没有什么好的设计模式可以用异步服务器来服务长时间运行的任务?

谢谢!

4

1 回答 1

8

只需运行您长时间运行的 CPU 密集型任务loop.run_in_executor()并通过loop.call_soon_threadsafe().

如果您的工作不是 CPU 而是 IO 绑定(例如发送电子邮件),您可以通过loop.create_task()调用创建一个新任务。它看起来像产生新线程。

如果您不能使用即发即弃的方法,则需要使用像 RabbitMQ 这样的持久消息代理(有https://github.com/benjamin-hodgson/asynqp库,用于以异步方式与 Rabbit 通信)。

于 2016-02-12T21:11:03.033 回答