2016-02-12 135 views
5

我想每个人都知道如何处理django中的长时间运行任务:使用芹菜并放松。但是如果我想用aiohttp(或龙卷风)获得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个客户将不会服务。

也许,我应该运行任务看起来芹菜大和任务看起来小在主循环?

所以,我的问题:是否有任何良好的设计模式,用于服务与异步服务器长时间运行的任务?

谢谢!

+0

'asyncio'不会帮助您处理CPU绑定的任务。 – dirn

+0

@dirn只有IO绑定的任务和与服务器的不同类型的交互才是好的吗? – dmitry

+1

好的asyncio可以提供帮助,如果任务托管在单独的线程中(或者带有yield或subprocess的绿色线程,真正有趣),它会更加活跃。 Obv。,有问题 - 什么是ws连接死亡?有没有数据竞赛?那么“真正的更多的请求比资源” - 503 /队列/块/错误? –

回答

7

只需运行您的长时间运行的CPU限制任务loop.run_in_executor()并发送进度通知loop.call_soon_threadsafe()

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

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