2018-11-28-Python全栈开发-day90-分支开发0--rabbitmq

rabbitmq理论知识

  可以当作一个邮局,是一个消息队列,生产者将消息放入队列,消费者在队列中取消息。rabbitqm是一个服务器,不同的程序都可以通过rabbitmq来进行通讯。

1.队列queue

  不同的程序可以确定不同的队列来进行信息的传输,生产者将消息放在队列中,消费者从队列中获取信息。多个消费者可以同时从队列中取数据,而且rabbitmq是公平的,给多个消费者平均的发消息,而不是像线程一样来抢资源。

  1.1 多个消费者可能出现的问题

  1)若消费者没有处理完消息就宕机,则有可能会导致这条消息丢失,为了避免这种情况,每个消费者完成了一个消息,服务器会检测消费者的状态,是否断开了连接,消费者都必须给rabbitmq服务器返回一个回执来进行确定,此时rabbitmq才会从队列中删除这个消息,但是只要消费者没有断开连接,且没有返回回执,则这个消息一直在队列中。

  2)若多个消费者处理消息的能力不同,当第一个消费者刚处理一半时,又轮到给这个消费者发消息,则会出现问题,

    可以通过设置prefetchcount来设置每次给消费者的消息数,每次只给一个,这样当检测到正在处理时,则不会给他发消息。

2.exchange

  在rabbitmq中,实际上服务器并不是直接将消息放入队列,而是将消息放入交换机,交换机根据不同的规则,来确定发送的消费者

  2.1 rounting key

    生产者在将消息发送给ex的时候,一般会指定一个rounting key,也就是发送规则,

  2.2 binding

    binding的作用是将交换机和队列关联起来,这样就可以通过交换机放队列里发数据

  

 

 

 

1.消息确认

  

当处理一个比较耗时得任务的时候,你也许想知道消费者(consumers)是否运行到一半就挂掉。当前的代码中,当消息被RabbitMQ发送给消费者(consumers)之后,马上就会在内存中移除。这种情况,你只要把一个工作者(worker)停止,正在处理的消息就会丢失。同时,所有发送到这个工作者的还没有处理的消息都会丢失。

我们不想丢失任何任务消息。如果一个工作者(worker)挂掉了,我们希望任务会重新发送给其他的工作者(worker)。

为了防止消息丢失,RabbitMQ提供了消息响应(acknowledgments)。消费者会通过一个ack(响应),告诉RabbitMQ已经收到并处理了某条消息,然后RabbitMQ就会释放并删除这条消息。

如果消费者(consumer)挂掉了,没有发送响应,RabbitMQ就会认为消息没有被完全处理,然后重新发送给其他消费者(consumer)。这样,及时工作者(workers)偶尔的挂掉,也不会丢失消息。

消息是没有超时这个概念的;当工作者与它断开连的时候,RabbitMQ会重新发送消息。这样在处理一个耗时非常长的消息任务的时候就不会出问题了。

消息响应默认是开启的。之前的例子中我们可以使用no_ack=True标识把它关闭。是时候移除这个标识了,当工作者(worker)完成了任务,就发送一个响应。

def callback(ch, method, properties, body):
    print " [x] Received %r" % (body,)
    time.sleep( body.count('.') )
    print " [x] Done"
    ch.basic_ack(delivery_tag = method.delivery_tag)

channel.basic_consume(callback,
                      queue='hello')

2.消息持久化

  如果你没有特意告诉RabbitMQ,那么在它退出或者崩溃的时候,将会丢失所有队列和消息。为了确保信息不会丢失,有两个事情是需要注意的:我们必须把“队列”和“消息”设为持久化。

首先,为了不让队列消失,需要把队列声明为持久化(durable):

channel.queue_declare(queue='hello', durable=True)

这时候,我们就可以确保在RabbitMq重启之后queue_declare队列不会丢失。另外,我们需要把我们的消息也要设为持久化——将delivery_mode的属性设为2。

  

channel.basic_publish(exchange='',
                      routing_key="task_queue",
                      body=message,
                      properties=pika.BasicProperties(
                         delivery_mode = 2, # make message persistent
                      ))

3.公平调度

  我们可以使用basic.qos方法,并设置prefetch_count=1。这样是告诉RabbitMQ,再同一时刻,不要发送超过1条消息给一个工作者(worker),直到它已经处理了上一条消息并且作出了响应。这样,RabbitMQ就会把消息分发给下一个空闲的工作者(worker)。

  

channel.basic_qos(prefetch_count=1)

===

 

整合代码

 发送者

  

#!/usr/bin/env python
import pika
import sys

connection = pika.BlockingConnection(pika.ConnectionParameters(
        host='localhost'))#创建连接
channel = connection.channel()#创建队列

channel.queue_declare(queue='task_queue', durable=True)#声明队列并且持久化

message = ' '.join(sys.argv[1:]) or "Hello World!"
channel.basic_publish(exchange='',
                      routing_key='task_queue',
                      body=message,
                      properties=pika.BasicProperties(
                         delivery_mode = 2, # make message persistent
                      ))#持久化
print " [x] Sent %r" % (message,)
connection.close()


#已经去掉no_ask 所以会有反馈

 消费者

  

#!/usr/bin/env python
import pika
import time

connection = pika.BlockingConnection(pika.ConnectionParameters(
        host='localhost'))#创建连接
channel = connection.channel()#创建队列

channel.queue_declare(queue='task_queue', durable=True)#连接队列并且持久化
print ' [*] Waiting for messages. To exit press CTRL+C'

def callback(ch, method, properties, body):
    print " [x] Received %r" % (body,)
    time.sleep( body.count('.') )
    print " [x] Done"
    ch.basic_ack(delivery_tag = method.delivery_tag)

channel.basic_qos(prefetch_count=1)#公平调度
channel.basic_consume(callback,
                      queue='task_queue')

channel.start_consuming()

 发布订阅

  将一条消息分发给多个接收者,类似于广播。

 生产者:

  登录rabbitmq服务器,建立队列,声明交换机名称和类型,确定消息类型,将消息发送到交换机,

 消费者:

  登录到rabbitmq服务器,建立队列,声明交换机类型和名称,建立临时队列,名称,使用后删除,将队列和交换机进行绑定,进行接收,制定回调函数,

 

转载于:https://www.cnblogs.com/hai125698/p/10040938.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值