web2py中的异步后台处理
我需要在一个web2py应用中处理一个耗时和占用内存很大的过程,这个过程是在控制器方法里调用的,最好是异步处理。
我的具体需求是通过 stdlib.subprocess
来调用一个进程,并且希望在这个进程结束之前,不让它阻塞网络服务器,不过我也愿意尝试其他的方法。
- 如果能提供一些实际的例子,那就更好了。
- 推荐一些第三方库也非常欢迎。
- 不需要/不想使用CRON调度。
3 个回答
这件事比想象中要复杂。注意在stdlib.subprocess 文档中提到的死锁警告。如果你不介意程序被阻塞的话,使用 Popen.communicate 就很简单。为了避免阻塞,你可以通过线程来管理这个进程,使用 stdlib.subprocess。
我最喜欢处理子进程的方法是使用Twisted 的 spawnProcess。不过,让 Twisted 和其他框架配合起来并不容易。
也许可以看看书中关于在后台运行任务的部分。你可以使用新的调度器,或者自己做一个简单的队列(比如发送邮件的例子)。还有一个web2py-celery 插件,不过我不太清楚它现在的状态如何。
假设你需要同时启动多个后台任务,解决这个问题的办法就是使用任务队列。我听说过Celery和RabbitMQ这两个工具,它们都是不错的第三方选择。而web2py也有自己的任务队列系统,可能能满足你的需求。
使用这些工具时,你需要定义一个函数,这个函数就是你希望后台进程执行的操作。然后,你要启动任务队列的工作者。根据web2py的手册和论坛的说法,你可以通过在web2py的定时任务系统中使用@reboot语句来实现,这样每当网络服务器启动时就会触发这个任务。如果这个方法不太合适,可能还有其他启动工作者的方式。
在你的控制器中,你会把一个任务插入到任务队列里,并将任何必要的参数作为输入传递给这个函数(注意,后台函数和控制器不在同一个环境中运行,所以它无法直接访问会话、数据库等内容,除非你明确地把相应的值传递给任务函数)。
现在,如何将后台操作的结果返回给用户呢?当你把一个任务插入到任务队列时,你应该会收到一个唯一的任务ID。接下来,你需要在控制器中实现一些逻辑(可以是一个期待AJAX调用的东西,或者是一个不断刷新的页面,直到任务完成),这个逻辑会调用任务队列的API来检查指定任务的状态。如果任务的状态是“完成”,就把数据返回给用户。如果还没完成,就继续等待。