在多个Django进程之间存储任务状态
我正在搭建一个日志桥梁,用于连接RabbitMQ消息和Django应用程序,以便将后台任务的状态存储在数据库中,方便后续的调查和审查,同时也能通过Django的管理界面重新发布任务。我觉得这没什么特别的,就是一个标准的生产者-消费者模式。
- 网页应用程序将任务发布到消息队列,并在数据库中插入初始任务状态。
- 消费者是一个独立的Python进程,它处理消息,并根据任务的输出更新任务状态。
现在的问题是,有些任务在数据库中缺失,因此从未被执行。我怀疑这是因为消费者在数据库提交之前就收到了消息。也就是说,从Model.save()返回并不意味着事务已经结束,这样整个通信就会中断。
有没有什么办法可以解决这个问题?也许可以使用某种事务后的信号?
谢谢大家的帮助。
2 个回答
网页应用程序将信息发布到消息队列,并将初始任务状态插入数据库。
不要这样做。
网页应用程序只需将信息发布到队列中。完成后,通过模板展示结果,结束网页交易。
然后,消费者从队列中获取信息并进行处理。例如,它可能会将日志添加到数据库中,以便展示给用户。消费者在执行操作时,也可能会将额外的状态信息发布到数据库。
实际上,许多应用程序都有多个队列和多个生产者/消费者关系。每个过程可能都会向日志中添加内容。
最后,展示部分必须总结这些日志条目。通常,最后一条记录就足够了,但有时你可能需要统计数量或获取早期条目的信息。
我觉得这个设计有点脆弱:你有一个网页应用,它会把信息发送到一个队列,然后再把初始状态插入数据库。如果消费者在网页应用还没来得及把初始状态存入数据库之前就处理了这个消息,会发生什么呢?
如果网页应用在消费者锁住数据库的时候尝试插入新的状态,又会怎样呢?
为了解决这个问题,网页应用应该把初始状态放到消息里,而消费者应该是唯一一个可以写入数据库的人。
[编辑] 你可能还会遇到日志记录的问题。检查一下网页应用和消费者之间的竞争是否会在日志中产生适当的错误,比如在不修改数据库的情况下发送消息到队列。
[编辑2] 一些想法:
比如只显示待处理任务的数量怎么样?这样,网页应用可以写入表1,而消费者写入表2,管理员可以查看两者之间的差异。
为什么网页应用看不到消费者在队列中的待处理任务呢?也许你应该有两个消费者。第一个消费者只负责把任务添加到数据库,提交后再把新行的主键发送给第二个消费者。管理员界面可以在第二个消费者写入的时候读取表。
最后一个想法:在把消息放入队列之前先提交事务。为此,你只需要向数据库发送“提交”命令。这可能会让人觉得奇怪(我也不建议在任何情况下这样做),但在这里,手动提交新行可能是有意义的(也就是在你返回到处理正常事务逻辑的框架之前)。