我应该如何为从Django调用的长时间进程存储状态?

时间:2009-05-12 15:39:06

标签: python django asynchronous amazon-s3 pyro

我正在开发一个允许用户上传文件的Django应用程序。我需要对这些文件执行一些服务器端处理,然后再将它们发送到Amazon S3。在阅读了对this questionthis blog post的回复后,我认为处理此问题的最佳方式是让我的视图处理程序在Pyro远程对象上调用一个方法来异步执行处理,然后立即将Http 200返回给客户端。我有这个原型,它似乎运行良好,但是,我还想存储处理的状态,以便客户端可以轮询应用程序,看看文件是否已被处理并上传到S3。

我可以轻松地处理轮询,但我不确定存储进程状态的适当位置。它需要由Pyro进程写入,并且可以通过我的轮询视图读取。

  • 我犹豫是否要在数据库中添加列,这些数据应该只持续30到60秒。
  • 我考虑过使用Django的low-level cache API并使用文件ID作为密钥,但是,我不相信这正是缓存框架的设计目标,我不确定那些可能出现的无法预料的问题走这条路。
  • 最后,我考虑过在Pyro对象中存储状态进行处理,但是后来我似乎还需要添加一个布尔“processing_complete”数据库列,以便视图知道是否从Pyro查询状态对象。

当然,还有一些数据完整性问题与数据库的解耦状态(如果服务器发生故障并且所有这些数据都在内存中会发生什么?)。我将听到更多经验丰富的Web应用程序开发人员如何处理这种状态处理。

3 个答案:

答案 0 :(得分:6)

我们通过在数据库中包含“请求”表来完成此操作。

当上传到达时,我们创建上传的File对象,并创建一个Request。

我们启动后台批处理器。

我们返回200“我们正在处理它”页面 - 它显示了请求及其状态。

我们的批处理器使用Django ORM。完成后,它会更新Request对象。我们可以(但不)发送电子邮件通知。大多数情况下,我们只是更新状态,以便用户可以再次登录并看到处理已完成。


批处理服务器架构说明。

这是一个WSGI服务器,它在端口上等待批处理请求。该请求是一个带有ID号的REST POST;批处理器在数据库中查找并处理它。

服务器由我们的REST界面自动启动。如果它没有运行,我们就会产生它。这使得用户交易看起来很慢,但是,哦。它不应该崩溃。

另外,我们有一个简单的crontab来检查它是否正在运行。在“你还活着吗?”之间最多会缩短30分钟。检查。我们没有正式的启动脚本(我们在带有mod_wsgi的Apache下运行),但我们可能会创建一个触发WSGI文件的“重启”脚本,然后对执行运行状况检查的URL执行POST(并启动批处理器)。

当批处理服务器启动时,可能存在从未获得过POST的未处理请求。因此,默认启动是将所有工作从请求队列中拉出来 - 假设它可能遗漏了某些东西。

答案 1 :(得分:5)

我知道这是一个古老的问题,但有人可能会发现我的答案在这段时间后仍然有用,所以这里就是这样。

您当然可以将数据库用作队列,但是有完全为此目的而开发的解决方案。

AMQP就是为了这个而做的。与CeleryCarrot以及RabbitMQZeroMQ等代理服务器一起使用。

这就是我们在最新项目中使用的内容,它运作良好。

对于你的问题,芹菜和RabbitMQ似乎是最合适的。 RabbitMQ提供了消息的持久性,Celery为轮询提供了简单的视图,以检查并行运行的进程的状态。

您可能也对octopy感兴趣。

答案 2 :(得分:1)

所以,这是你需要的工作队列。对于你的情况,我绝对会使用数据库来保存状态,即使这些状态是短暂的。听起来这样可以满足您的所有要求,并且实现起来并不十分困难,因为您已经拥有了所有可用的移动部件。除非你需要更复杂的东西,否则请保持简单。

如果你需要更强大或更复杂的东西,我会看Gearman之类的东西。