Django + RabbitMQ + Celery都在不同的机器上(服务器)

 每天听点心理学_961 发布于 2022-12-04 03:58

我设法DjangoRabbitMQCelery单机上工作.我已按照此处的说明操作.现在我想让它们一起工作,但是当它们在不同的服务器上时.我不想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接口进行交互).

此外,我需要Celery在两个或更多服务器上安装工作人员,并且我只想RabbitMQ根据消息中的某个字段通知其中一个服务器.如果这很复杂,我可以检查每个任务(在不同的机器上),例如:这是你应该做的事情(比如检查消息中的ip地址字段),如果它不仅仅是停止执行任务.

我怎样才能做到这一点?如果可能的话,我更喜欢代码+配置示例而不仅仅是理论解释.

编辑:

我认为对于我的用例芹菜是总开销.使用自定义客户端的简单RabbitMQ路由将完成这项工作.我已经尝试过简单的用例(一个服务器),它运行得很好.应该很容易使通信多服务器准备就绪.我不喜欢芹菜.这是"神奇的",隐藏了太多的细节,并不容易配置.但我会留下这个问题,因为我对别人的意见很感兴趣.

miraculixx.. 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应用程序.

甚至更简单的选择

上述存根任务的替代方法是按名称发送任务:

>>> app.send_task('tasks.add', args=[2, 2], kwargs={})

关于消息模式

另外,我需要在两个或更多服务器上安装Celery工作器,我希望RabbitMQ只根据消息中的某个字段通知其中一个.

RabbitMQ提供了几种消息传递模式,他们的教程编写得非常好,而且非常重要.通过简单的队列/交换设置可以轻松实现您想要的(一个工作人员处理的一条消息),如果您不执行任何其他操作,则(至少使用Celery)是默认设置.如果您需要特定工作人员来处理特定任务/响应特定消息,请使用Celery的任务路由,该任务路由与RabbitMQ的队列和交换概念密切配合.

权衡

我认为对于我的用例芹菜是总开销.使用自定义客户端的简单RabbitMQ路由将完成这项工作.我已经尝试过简单的用例(一个服务器),它运行得很好.

当然,您可以开箱即用RabbitMQ,代价是必须处理RabbitMQ提供的低级API.Celery添加了一个任务抽象,使得构建任何生产者/消费者场景非常简单,基本上只使用普通的Python函数或方法.请注意,这不是对RabbitMQ或Celery的更好/更差的判断 - 与工程决策一样,需要权衡:

如果您使用Celery,您可能会失去RabbitMQ API的一些灵活性,但您可以轻松开发,同时获得开发速度和更低的部署复杂性 - 它基本上只是起作用.

如果您直接使用RabbitMQ,您将获得灵活性,但这会带来您需要自行管理的部署复杂性.

根据您项目的要求,任何一种方法都可能有效 - 您的电话,确实.

任何足够先进的技术都与魔术无法区分 ;-)

我不喜欢芹菜.这是"神奇的",隐藏了太多的细节,并不容易配置.

我会选择不同意.在Arthur C. Clarke的意义上,它可能是"神奇的" ,但如果将它与普通的RabbitMQ设置进行比较,它肯定很容易配置.当然,如果你也是做RabbitMQ设置的人,它可能只是添加一层你从未获得任何东西的抽象.也许你的开发者会?

1 个回答
  • 缺点

    我怎样才能做到这一点?

    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应用程序.

    甚至更简单的选择

    上述存根任务的替代方法是按名称发送任务:

    >>> app.send_task('tasks.add', args=[2, 2], kwargs={})
    <AsyncResult: 373550e8-b9a0-4666-bc61-ace01fa4f91d>
    

    关于消息模式

    另外,我需要在两个或更多服务器上安装Celery工作器,我希望RabbitMQ只根据消息中的某个字段通知其中一个.

    RabbitMQ提供了几种消息传递模式,他们的教程编写得非常好,而且非常重要.通过简单的队列/交换设置可以轻松实现您想要的(一个工作人员处理的一条消息),如果您不执行任何其他操作,则(至少使用Celery)是默认设置.如果您需要特定工作人员来处理特定任务/响应特定消息,请使用Celery的任务路由,该任务路由与RabbitMQ的队列和交换概念密切配合.

    权衡

    我认为对于我的用例芹菜是总开销.使用自定义客户端的简单RabbitMQ路由将完成这项工作.我已经尝试过简单的用例(一个服务器),它运行得很好.

    当然,您可以开箱即用RabbitMQ,代价是必须处理RabbitMQ提供的低级API.Celery添加了一个任务抽象,使得构建任何生产者/消费者场景非常简单,基本上只使用普通的Python函数或方法.请注意,这不是对RabbitMQ或Celery的更好/更差的判断 - 与工程决策一样,需要权衡:

    如果您使用Celery,您可能会失去RabbitMQ API的一些灵活性,但您可以轻松开发,同时获得开发速度和更低的部署复杂性 - 它基本上只是起作用.

    如果您直接使用RabbitMQ,您将获得灵活性,但这会带来您需要自行管理的部署复杂性.

    根据您项目的要求,任何一种方法都可能有效 - 您的电话,确实.

    任何足够先进的技术都与魔术无法区分 ;-)

    我不喜欢芹菜.这是"神奇的",隐藏了太多的细节,并不容易配置.

    我会选择不同意.在Arthur C. Clarke的意义上,它可能是"神奇的" ,但如果将它与普通的RabbitMQ设置进行比较,它肯定很容易配置.当然,如果你也是做RabbitMQ设置的人,它可能只是添加一层你从未获得任何东西的抽象.也许你的开发者会?

    2022-12-11 02:14 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有