我设法让Django
和RabbitMQ
以及Celery
在单机上工作。我已按照here的说明进行操作。现在我想让它们一起工作,但是当它们在不同的服务器上时。我不希望Django
对Celery
和Celery
了解Django
。
所以,基本上我只想在Django
中向RabbitMQ
队列发送一些消息(可能是id,任务类型,也许是其他一些信息),然后我想要RabbitMQ
来将该消息(如果可能的话)发布到另一台服务器上的Celery
。 Celery/Django
不应该彼此了解,基本上我想要的架构很容易替换其中任何一个。
现在,我已经在Django
多次调用,例如
create_project.apply_async(args, countdown=10)
我想用类似的调用直接替换为RabbitMQ(正如我所说Django
不应该依赖Celery
)。然后,RabbitMQ
应该通知Celery
(如果可能的话)并且Celery
将完成其工作(可能与Django
但通过REST
接口进行交互。)< / p>
另外,我需要在两台或更多服务器上安装Celery
个工作人员,我希望RabbitMQ
只根据消息中的某个字段通知其中一个。如果这很复杂,我可以检查每个任务(在不同的机器上),例如:这是你应该做的事情(比如检查消息中的ip地址字段),如果它不仅仅停止执行任务。
我怎样才能做到这一点?如果可能的话,我更喜欢代码+配置示例而不仅仅是理论解释。
修改
我认为对于我的用例芹菜是总开销。简单的RabbitMQ 使用自定义客户端进行路由将完成工作。我已经尝试过简单了 用例(一个服务器),它完美地工作。它应该很容易 使通信多服务器准备就绪。我不喜欢芹菜。它是 &#34;魔法&#34;,隐藏太多细节,配置起来并不容易。但我会留下这个问题,因为我对别人的意见感兴趣。
答案 0 :(得分:5)
缺少
我怎样才能做到这一点?
Celery只发送任务名称和一系列参数作为消息正文。那就是你的场景绝对符合Celery的运作方式。
如果可能,我更喜欢代码+配置示例而不仅仅是理论解释。
对于客户端应用程序,即您的Django应用程序,定义存根任务,如下所示:
@task
def foo():
pass
对于Celery处理,在远程服务器上,定义要执行的实际任务。
@task
def foo():
pass
重要的是,任务存在于双方的相同Python包中(即app.tasks.py
,否则Celery将无法将消息与实际任务相匹配。
请注意,如果您设置了CELERY_ALWAYS_EAGER=True
,这也意味着您的Django应用程序变得不可测试,除非您将Celery应用程序的tasks.py
本地提供给Django应用程序。
更简单的替代方案
上述存根任务的替代方法是发送任务by name:
>>> app.send_task('tasks.add', args=[2, 2], kwargs={})
<AsyncResult: 373550e8-b9a0-4666-bc61-ace01fa4f91d>
关于消息模式
另外,我需要在两台或多台服务器上安装Celery工作器,我希望RabbitMQ只根据消息中的某个字段通知其中一个。
RabbitMQ提供了几种消息传递模式,它们的tutorials编写得非常好,而且非常重要。通过简单的队列/交换设置可以轻松实现您想要的(一个工作人员处理的一条消息),如果您不做其他任何事情,那么(至少使用Celery)是默认设置。如果您需要特定工作人员来处理特定任务/响应特定消息,请使用Celery的任务routing,该任务与RabbitMQ的队列和交换概念密切配合。
权衡
我认为对于我的用例芹菜是总开销。使用自定义客户端的简单RabbitMQ路由将完成这项工作。我已经尝试过简单的用例(一个服务器),它运行得很好。
当然,您可以开箱即用RabbitMQ,代价是必须处理RabbitMQ提供的低级API。 Celery添加了一个任务抽象,使得构建任何生产者/消费者场景非常简单,基本上只使用普通的Python函数或方法。请注意,这不是对RabbitMQ或Celery的更好/更差的判断 - 与工程决策一样,需要进行权衡:
如果您使用Celery,您可能会失去RabbitMQ API的一些灵活性,但您可以轻松开发,同时获得开发速度和更低的部署复杂性 - 它基本上只是起作用。
如果您直接使用RabbitMQ,您将获得灵活性,但这会带来您需要自行管理的部署复杂性。
根据项目的要求,任何一种方法都可能有效 - 您的电话,确实。
任何足够先进的技术都无法与魔法区分开来; - )
我不喜欢芹菜。它是&#34;魔法&#34;,隐藏了太多细节,并不容易配置。
我会选择不同意。它可能是&#34;魔法&#34;在Arthur C. Clarke's意义上,但如果将它与普通的RabbitMQ设置进行比较,它肯定很容易配置。当然,如果你也是那个做RabbitMQ设置的人,它可能只是添加一层你从未获得任何东西的抽象层。也许你的开发人员会这样做?