5

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

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

  • 我很犹豫是否将列添加到数据库中以获取实际上应该只持续 30 到 60 秒的数据。
  • 我考虑过使用 Django 的低级缓存 API并使用文件 id 作为键,但是,我不相信这真的是缓存框架的设计目的,我不确定可能会出现什么不可预见的问题这条路线。
  • 最后,我考虑过将状态存储在 Pyro 对象中进行处理,但看起来我仍然需要添加一个布尔“processing_complete”数据库列,以便视图知道是否从 Pyro 对象查询状态。

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

4

3 回答 3

6

我们通过在数据库中有一个“请求”表来做到这一点。

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

我们启动后台批处理器。

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

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


批处理服务器架构说明。

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

服务器由我们的 REST 接口自动启动。如果它没有运行,我们生成它。这使得用户事务看起来很慢,但是,哦,好吧。它不应该崩溃。

此外,我们有一个简单的 crontab 来检查它是否正在运行。最多在“你还活着吗?”之间下降30分钟。检查。我们没有正式的启动脚本(我们在 Apache 下使用 mod_wsgi 运行),但我们可以创建一个“重新启动”脚本,该脚本会触及 WSGI 文件,然后对执行健康检查的 URL 执行 POST(并启动批处理器)。

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

于 2009-05-12T16:12:37.977 回答
5

我知道这是一个老问题,但即使过了这么久,有人可能会发现我的答案很有用,所以就这样吧。

您当然可以将数据库用作队列,但也有专门为此目的开发的解决方案。

AMQP就是为此而生的。与CeleryCarrot以及RabbitMQZeroMQ等代理服务器一起使用。

这就是我们在最新项目中使用的,并且效果很好。

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

您可能还对octopy感兴趣。

于 2009-12-14T07:06:12.197 回答
1

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

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

于 2009-05-12T18:13:47.187 回答