RabbitMQ+Celery

RabbitMQ+Celery

最近用到RabbitMQ+Celery框架进行开发分布式任务队列,这里进行一下整理总结,菜鸟欢迎批评指正。

RabbitMQ

一些术语

  1. 官网:http://www.rabbitmq.com/
  2. RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。A
  3. MQ:消息队列(Message Queue),应用程序A可以给应用程序B发送消息,能够有效解耦,支持高并发,支持异步操作等等。
  4. AMQP:Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。
  5. 生产者:消息的生产者,将消息发送到MQ
  6. 消费者:消息的消费者,从MQ接收消息并进行处理
  7. Exchange:交换器,将生产者的消息根据规则路由到不同的队列以便不同的消费者拿到对应的消息。
  8. RabbitMQ常用的Exchange Type有三种:fanout、direct、topic。

fanout:把所有发送到该Exchange的消息投递到所有与它绑定的队列中,广播。

direct:把消息投递到那些binding key与routing key完全匹配的队列中。

topic:将消息路由到binding key与routing key模式匹配的队列中。

https://gss2.bdstatic.com/-fo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=8732641cf703738dca470470d272db34/902397dda144ad3467b19c3bd1a20cf431ad857b.jpg

  1. RabbitMQ支持消息确认,RabbitMQ收到消息回执(Message acknowledgment)后才将该消息从Queue中移除;如果RabbitMQ没有收到回执并检测到消费者的RabbitMQ连接断开,则RabbitMQ会将该消息发送给其他消费者(如果存在多个消费者)进行处理。
  2. RabbitMQ支持消息持久化,可以将Queue与Message都设置为可持久化的(durable),这样可以保证绝大部分情况下我们的RabbitMQ消息不会丢失。但依然解决不了小概率丢失事件的发生(可以通过事务解决)。
  3. RabbitMQ支持RPC。

Demo

官网上有教程,包括简单队列,worker模式,Publish/Subscribe模式,Routing模式,Topics模式。

简单队列中,producer和consumer直接指定routing key 为queue,这种模式一般不用。

worker模式中,和上面比较像,只是消费者变为多个。这种模式下一条消息只能被一个消费者消费,消费快的消费者会消费更多的消息。

Publish/Subscribe模式中,需要指定exchange type为fanout,一条消息会被所有的消费者消费。

Routing模式中,指定exchange type为direct,同时需要指定routing key好指定路由到哪个队列上。

Topics模式中,在Routing基础上,将routing key可以设置为模糊匹配的模式。*可以匹配任一个单词,#可以匹配零个或多个单词。如test.*可以匹配test.a, test.b等。

这里只附上topics模式的demo,详细可登陆官网。

producer.py

import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()

channel.exchange_declare(
exchange='topic_logs',
                        
exchange_type='topic')

routing_key =
'test.v'  # *.a consumer1能收到,test.*consumer2能收到,test.a两者都能收到

message = '%s Hello World' % routing_key
channel.basic_publish(
exchange='topic_logs',
                     
routing_key=routing_key,
                     
body=message)
print(" [x] Sent %r:%r" % (routing_key, message))
connection.close()

consumer1.py

import pika



connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))

channel = connection.channel()



channel.exchange_declare(exchange='topic_logs',

                         exchange_type='topic')



queue_name = 'test_topic_a'

channel.queue_declare(queue=queue_name, durable=True)



binding_keys = ['*.a']



for binding_key in binding_keys:

    channel.queue_bind(exchange='topic_logs',

                       queue=queue_name,

                       routing_key=binding_key)





def callback(ch, method, properties, body):

    print("%s:%s" % (method.routing_key, body))





channel.basic_consume(callback,

                      queue=queue_name,

                      no_ack=True)



channel.start_consuming()

在consumer2.py中,将queue_name = 'test_topic_b',binding_keys = ['test.*']即可。

Celery

Celery是一个简单,灵活,可靠的分布式系统,用于处理大量消息,同时为操作提供维护此类系统所需的工具。Celery是一个任务队列,专注于实时处理,同时还支持任务调度。

Celery的架构由三部分组成,消息中间件(message broker),任务执行单元(worker)和任务执行结果存储(task result store)组成。Celery作为MQ的消费者,根据接收的消息进行任务调度,同时执行任务的结果可以进行存储。如图:

http://static.open-open.com/lib/uploadImg/20150314/20150314100608_187.png

Demo

这里使用kombu消息框架。

producer.py

# coding:utf8

import datetime

from uuid import uuid4

from kombu import Connection, Exchange



# RabbitMQ Config

MQ_HOST = 'localhost'

MQ_USER = 'guest'

MQ_PASSWORD = 'guest'

MQ_PORT = 5672

VIRTUAL_HOST = '/'

EXCHANGE_NAME = 'test_celery'



routing_key = 'celery.test'

queue_name = 'test_celery_work_queue'

message = 'time now is %s' % datetime.datetime.now()

method_name = 'test_work'



_url = 'amqp://{0}:{1}@{2}:{3}/{4}'.format(MQ_USER, MQ_PASSWORD, MQ_HOST, MQ_PORT, VIRTUAL_HOST)

with Connection(_url) as conn:

    producer = conn.Producer(serializer='json')

    body_dict = {"args": [message], "id": str(uuid4()),

                 "task": method_name  # 要调用的work方法

                 }

    producer.publish(

        body=body_dict,

        routing_key=routing_key,

        exchange=Exchange(EXCHANGE_NAME, 'topic'),

        retry=True,

    )

task.py

# coding:utf8

import os



from celery import Celery

from kombu import Queue, Exchange



# RabbitMQ config

RABBITMQ_HOSTS = "localhost"

RABBITMQ_PORT = 5672

RABBITMQ_VHOST = '/'

RABBITMQ_USER = 'guest'

RABBITMQ_PWD = 'guest'

# celery config

CELERY_IMPORTS = ('task',)

BROKER_URL = 'amqp://%s:%s@%s:%d/%s' % (RABBITMQ_USER, RABBITMQ_PWD, RABBITMQ_HOSTS, RABBITMQ_PORT, RABBITMQ_VHOST)

CELERY_TRACK_STARTED = True

CELERYD_CONCURRENCY = # 配置会启用执行任务的线程数

CELERYD_PREFETCH_MULTIPLIER = # how many messages a time

CELERY_TASK_RESULT_EXPIRES = 60

CELERYD_HIJACK_ROOT_LOGGER = False

CELERY_DEFAULT_QUEUE = 'DEFAULT_QUEUE'

# 只要配置好路由器和队列,使得celery能够接收到消息,其会根据方法签名自行选择方法进行执行

CELERY_QUEUES = (

    Queue('test_celery_work_queue', Exchange('test_celery', type='topic'), routing_key='celery.test'),

)



celery = Celery("task", broker=BROKER_URL)





@celery.task(name="test_work", ignore_result=True, serializer="json")

def ipa_unpack(message):

    print 'receive', message

    print 'doing my work!'





if __name__ == "__main__":

    os.system(  # 在工作目录下使用命令行执行

        "python -m celery worker -A task -Q test_celery_work_queue --without-gossip --without-mingle --without-heartbeat -l INFO")

输出:

[2018-08-05 15:30:15,813: INFO/MainProcess] Received task: test_work[ef2cb7b0-ebae-4887-b329-de4c63806336]

[2018-08-05 15:30:15,815: WARNING/Worker-1] receive

[2018-08-05 15:30:15,815: WARNING/Worker-1] time now is 2018-08-05 15:30:15.759000

[2018-08-05 15:30:15,815: WARNING/Worker-1] doing my work!

[2018-08-05 15:30:15,822: INFO/MainProcess] Task test_work[ef2cb7b0-ebae-4887-b329-de4c63806336] succeeded in 0.0090000629425s: None

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Django Celery 是一个用于 Django 框架的分布式任务队列工具。它结合了 Django 的 Web 开发能力和 Celery 的异步任务处理能力。通过使用 Celery,你可以将耗时的任务(如发送电子邮件、处理图像、执行定时任务等)从主线程中分离出来,以提高应用的性能和响应速度。 你可以通过以下步骤来集成 Django 和 Celery: 1. 安装 Celery:在命令行中使用 pip 安装 Celery 库:`pip install celery` 2. 配置 Celery:在 Django 项目的 settings.py 文件中配置 Celery 相关的设置,主要包括消息代理器(message broker)的设置和任务结果存储的设置。 3. 创建任务:在 Django 项目中创建需要异步执行的任务。任务是一个 Python 函数,使用 `@task` 装饰器进行标记。 4. 启动 Celery Worker:在命令行中使用 `celery -A your_project_name worker --loglevel=info` 启动 Celery Worker,该命令会监听并执行任务队列中的任务。 5. 触发任务:在你的 Django 代码中调用任务函数,可以使用 `your_task.delay()` 来触发异步执行任务。 这样,当你触发任务时,它会被添加到 Celery 的任务队列中,并由 Celery Worker 异步执行。执行结果可以存储在指定的结果存储中,也可以通过回调函数获取。 注意:配置消息代理器和结果存储器时,你可以选择使用不同的后端,如 RabbitMQ、Redis、Amazon SQS 等。 以上是关于 Django Celery 的简要介绍和基本使用步骤,如果你有具体问题或需要更详细的指导,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值