关于Python / Django和消息队列的build议
我在Django有一个应用程序,需要在各种用例中向用户发送大量的电子邮件。 我不想在应用程序内同步处理这个问题,原因很明显。
有任何人build议消息队列服务器与Python很好地集成,或者他们已经在Django项目上使用? 我的堆栈的其余部分是Apache,mod_python,MySQL。
到目前为止,我没有发现这个“好”的解决scheme。 我有一些更严格的软实时要求(从一个纸箱拍摄的照片被标记),所以可能其中一种方法对您来说足够快。 我假设电子邮件可以等待几分钟。
- 由cron作业处理的数据库中的“待办事项列表”。
- 数据库中的“待办事项列表”由一个守护进程持续处理。
- 使用通过UDP数据包通知Web服务器的自定义守护进程(在今天的生产中)。 基本上我自己的排队系统与IP栈来处理队列。
- 使用ActiveMQ作为消息代理 – 由于稳定性问题,这并没有解决。 另外对我来说,Java守护进程通常有点丰满
- 在CouchDB中使用更新触发器。 不错,但更新触发器并不意味着做沉重的image processing,所以不适合我的问题。
到目前为止,我还没有尝试RabbitMQ和XMPP / ejabebrd来处理这个问题,但他们在我的下一个尝试列表。 RabbitMQ在2008年得到了体面的Python连接,并且有大量的XMPP库。
但是也许你需要的是本地机器上正确configuration的邮件服务器。 这可能会允许您将邮件同步转储到本地邮件服务器,从而使您的整个软件栈变得更加简单。
在你的具体情况下,它只是一个电子邮件队列,我会采取简单的方法,并使用django邮件 。 作为一个好的方面,还有其他可插拔的项目,足够聪明,当他们看到堆栈中的django邮件的优势。
至于更一般的队列解决scheme,我还没有尝试过这些,但是这里有一些看起来更有趣的列表:
- pybeanstalk / beanstalkd
- python接口的齿轮 (这可能是更有趣的C版本的齿轮的发布 )
- memcacheQ
- 跺脚
- 芹菜
Stompserver是一个不错的select。 它是轻量级的,易于安装和易于使用从Django / python。
我们有一个系统在生产中使用stompserver发送电子邮件和asynchronous处理其他工作。
Django将电子邮件保存到数据库,Django中的model.post_save处理程序向stompserver发送事件,stompserver将事件传递给执行asynchronous任务(发送电子邮件)的使用者进程。
它可以很好地扩展,因为您可以在运行时添加消费者stream程 – 两个消费者可以发送两倍的电子邮件,而消费者可以在不同的机器上。 一个小小的复杂情况是,每个消费者都需要自己的命名队列,因此Django需要知道有多less消费者可用,并以循环方式将事件发送到每个队列。 (两个使用相同队列的消费者都会得到每个消息=重复)。 如果你只想要一个消费者stream程,那么这不是一个问题。
我们以前有过连续轮询数据库的过程,但是发现它为系统增加了很多负载,即使没有需要处理的东西。
只需将电子邮件添加到数据库,然后编写另一个由任务计划程序实用程序(cron想到)运行的脚本来发送电子邮件。
你可能想看看pymq 。 它用python编写,与客户端进行HTTP会话,并为队列提供大量的监控和pipe理选项。
使用邮件基础结构解决这个问题有什么不妥之处吗? 就像每个应用程序服务器都运行自己的邮件守护进程,这些守护进程将排队所有本地提交的邮件,这些邮件将转发到一个集中的邮件服务器,从而完成邮件繁重工作
如果你已经安装了MySQL,你可以创build一个表来用作“待办事项列表”。
线程同步向表中添加作业,批处理任务在作业完成时删除作业。
这样,就不需要安装和学习更多的软件,只要你不发送大量的电子邮件(比如> 10 /秒),它就可以很好地工作。
这是一个懒惰,但正确和适当的解决scheme。 使用以下数据库表作为队列。
drop table if exists mailqueue; create table mailqueue ( id bigint primary key, subject text not null, body mediumtext not null, from varchar(255) not null, to varchar(255) not null );
发件人应该在这张表的最后插入新的行。
设置工作线程从另一端(最低的ID)一次popup一个邮件,然后尝试发送邮件。
你也可以使用扭曲这个。 但是在任何情况下都不会和django一起玩,它非常依赖部署场景。 最重要的是每个请求都必须由一个python进程提供服务,所以你需要以线程模式编译的apache。