send端

import pika

credentials = pika.PlainCredentials('zhou', '')
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='10.0.1.14',credentials=credentials))
channel = connection.channel() #声明queue
channel.queue_declare(queue='hello') #n RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
channel.basic_publish(exchange='',
routing_key='hello',
body='Hello World!')
print(" [x] Sent 'Hello World!'")
connection.close()

receive端

import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
'localhost'))
channel = connection.channel() #You may ask why we declare the queue again ‒ we have already declared it in our previous code.
# We could avoid that if we were sure that the queue already exists. For example if send.py program
#was run before. But we're not yet sure which program to run first. In such cases it's a good
# practice to repeat declaring the queue in both programs.
channel.queue_declare(queue='hello') def callback(ch, method, properties, body):
print(" [x] Received %r" % body) channel.basic_consume(callback,
queue='hello',
no_ack=True) print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

消费一个消息可能会花好几秒。你可能会问,如果如果一个消费者启动了一个长的任务,消息发了一半然后死了。按我们现在的代码,一旦rabbitmq传递了一个消息到给消费者,然后rabbitmq就迅速的将这个消息从内存里删除。在这种情况下,如果你kill了一个消费者,我们就会失去了这个正在传递的消息。

但是我们不想失去这个消息。如果一个消费者死了,我想把这个任务传给另一个消费者。

为了确保一个消息从不丢失,rabbitmq支持消息确认。消费者处理完信息后会向rabbitmq发送一个消息确认,这样rabbitmq就可以从内存里删除这个消息了。

如果一个消费者死掉了,没有发ack,rabbitmq就会知道这个消息没有传递成功,就会把这个消息重新存到queue里。

如果此时有其它的消费者在线,rabbitmq就会迅速的将这个消息传递给其它的的消费者。这样就确保了消息没有丢失,即使这个消费者是偶尔挂了。

根本就没有超时时间一说,当那个消费者挂了,rabbitmq会重新转发那条消息。即使这个消息处理了很长时间都没关系。

rabbitmq消息确认默认是开启的(no_ack=Fault)。在之前的例子里我们显然用的no_ack=True。

队列及消息持久化

生产者

import pika

credentials = pika.PlainCredentials('zhou', '')
# connection = pika.BlockingConnection(pika.ConnectionParameters(host=url_1,
# credentials=credentials, ssl=ssl, port=port))
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='10.0.1.14',credentials=credentials)) channel = connection.channel() # 声明queue,durable=True(队列持久化)
channel.queue_declare(queue='alex3',durable=True) # n RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
channel.basic_publish(exchange='',
routing_key='alex3', #send msg to this queue
body='Hello World!23',
properties=pika.BasicProperties(
delivery_mode=2, # 消息持久化
)
) print(" [x] Sent 'Hello World!2'")
connection.close()

消费者

import pika
import time
credentials = pika.PlainCredentials('zhou', '')
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='10.0.1.14',credentials=credentials)) channel = connection.channel()
# You may ask why we declare the queue again ‒ we have already declared it in our previous code.
# We could avoid that if we were sure that the queue already exists. For example if send.py program
# was run before. But we're not yet sure which program to run first. In such cases it's a good
# practice to repeat declaring the queue in both programs. channel.queue_declare(queue='alex3',durable=True)#队列持久化 def callback(ch, method, properties, body):
print(ch, method, properties) print(" [x] Received %r" % body)
time.sleep(1) channel.basic_consume(callback,
queue='alex3',
no_ack=True
)
channel.basic_qos(prefetch_count=1)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

消息公平分发

如果Rabbit只管按顺序把消息发到各个消费者身上,不考虑消费者负载的话,很可能出现,一个机器配置不高的消费者那里堆积了很多消息处理不完,同时配置高的消费者却一直很轻松。为解决此问题,可以在各个消费者端,配置perfetch=1,意思就是告诉RabbitMQ在我这个消费者当前消息还没处理完的时候就不要再给我发新消息了。

channel.basic_qos(prefetch_count=1)

生产者

import pika,sys

credentials = pika.PlainCredentials('zhou', '')
# connection = pika.BlockingConnection(pika.ConnectionParameters(host=url_1,
# credentials=credentials, ssl=ssl, port=port))
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='10.0.1.14',credentials=credentials)) 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()

消费者

import pika,time
credentials = pika.PlainCredentials('zhou', '')
# connection = pika.BlockingConnection(pika.ConnectionParameters(host=url_1,
# credentials=credentials, ssl=ssl, port=port))
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='10.0.1.14',credentials=credentials))
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(b'.'))
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消息发布\订阅(Publish\Subscribe)

当要采用广播发消息的时候就要用到exchange了。

exchange是一个很简单的东西,一端从生产者里接收消息,另一端把消息推送到队列里。exchange必须清除的知道它从生产者里接收的消息要发送给谁。接收到的消息是应该被追加到指定的queue里?还是应该追加到很多个queue里?或者是扔掉?这个规则都是根据exchange的类型来定义的。

exchange的类型:

fanout: 所有bind到此exchange的queue都可以接收消息
direct: 通过routingKey和exchange决定的那个唯一的queue可以接收消息
topic:所有符合routingKey(此时可以是一个表达式)的routingKey所bind的queue可以接收消息

   表达式符号说明:#代表一个或多个字符,*代表任何字符
      例:#.a会匹配a.a,aa.a,aaa.a等
          *.a会匹配a.a,b.a,c.a等
     注:使用RoutingKey为#,Exchange Type为topic的时候相当于使用fanout 

headers: 通过headers 来决定把消息发给哪些queue

fanout实例

send端

import pika
import sys credentials = pika.PlainCredentials('zhou', '')
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='10.0.1.14',credentials=credentials)) channel = connection.channel() channel.exchange_declare(exchange='logs', type='fanout') message = ' '.join(sys.argv[1:]) or "info: Hello World!" channel.basic_publish(exchange='logs',
routing_key='',
body=message) print(" [x] Sent %r" % message) connection.close()

recv端

import pika

credentials = pika.PlainCredentials('zhou', '')
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='10.0.1.14',credentials=credentials)) channel = connection.channel() channel.exchange_declare(exchange='logs',type='fanout') result = channel.queue_declare(exclusive=True) # 不指定queue名字,rabbit会随机分配一个名字,exclusive=True会在使用此queue的消费者断开后,自动将queue删除 queue_name = result.method.queue channel.queue_bind(exchange='logs',queue=queue_name) print(' [*] Waiting for logs. To exit press CTRL+C') def callback(ch, method, properties, body):
print(" [x] %r" % body) channel.basic_consume(callback,
queue=queue_name,
)
channel.start_consuming()

direct实例

send端

import pika
import sys credentials = pika.PlainCredentials('zhou', '')
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='10.0.1.14',credentials=credentials)) channel = connection.channel() channel.exchange_declare(exchange='direct_logs',type='direct') severity = sys.argv[1] if len(sys.argv) > 1 else 'info' message = ' '.join(sys.argv[2:]) or 'Hello World!' channel.basic_publish(exchange='direct_logs',
routing_key=severity, #error
body=message) print(" [x] Sent %r:%r" % (severity, message))
connection.close()

recv端

import pika
import sys credentials = pika.PlainCredentials('zhou', '')
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='10.0.1.14',credentials=credentials))
channel = connection.channel() channel.exchange_declare(exchange='direct_logs',type='direct')
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue severities = sys.argv[1:]
if not severities:
sys.stderr.write("Usage: %s [info] [warning] [error]\n" % sys.argv[0])
sys.exit(1) for severity in severities: #[error info warning]
channel.queue_bind(exchange='direct_logs',
queue=queue_name,
routing_key=severity)
print(' [*] Waiting for logs. To exit press CTRL+C')
def callback(ch, method, properties, body):
print(" [x] %r:%r" % (method.routing_key, body))
channel.basic_consume(callback,queue=queue_name,)
channel.start_consuming()

topic实例

send端

import pika
import sys credentials = pika.PlainCredentials('zhou', '')
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='10.0.1.14',credentials=credentials)) channel = connection.channel() channel.exchange_declare(exchange='topic_logs',type='topic') routing_key = sys.argv[1] if len(sys.argv) > 1 else 'anonymous.info' message = ' '.join(sys.argv[2:]) or 'Hello World!' channel.basic_publish(exchange='topic_logs',
routing_key=routing_key,
body=message)
print(" [x] Sent %r:%r" % (routing_key, message))
connection.close()

recv端

import pika
import sys credentials = pika.PlainCredentials('zhou', '')
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='10.0.1.14',credentials=credentials)) channel = connection.channel()
channel.exchange_declare(exchange='topic_logs',type='topic') result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue binding_keys = sys.argv[1:]
if not binding_keys:
sys.stderr.write("Usage: %s [binding_key]...\n" % sys.argv[0])
sys.exit(1) for binding_key in binding_keys:
channel.queue_bind(exchange='topic_logs',
queue=queue_name,
routing_key=binding_key) print(' [*] Waiting for logs. To exit press CTRL+C')
def callback(ch, method, properties, body):
print(" [x] %r:%r" % (method.routing_key, body)) channel.basic_consume(callback,queue=queue_name) channel.start_consuming()

rabbitmq的更多相关文章

  1. 消息队列——RabbitMQ学习笔记

    消息队列--RabbitMQ学习笔记 1. 写在前面 昨天简单学习了一个消息队列项目--RabbitMQ,今天趁热打铁,将学到的东西记录下来. 学习的资料主要是官网给出的6个基本的消息发送/接收模型, ...

  2. RabbitMq应用二

    在应用一中,基本的消息队列使用已经完成了,在实际项目中,一定会出现各种各样的需求和问题,rabbitmq内置的很多强大机制和功能会帮助我们解决很多的问题,下面就一个一个的一起学习一下. 消息响应机制 ...

  3. 如何优雅的使用RabbitMQ

    RabbitMQ无疑是目前最流行的消息队列之一,对各种语言环境的支持也很丰富,作为一个.NET developer有必要学习和了解这一工具.消息队列的使用场景大概有3种: 1.系统集成,分布式系统的设 ...

  4. RabbitMq应用一的补充(RabbitMQ的应用场景)

    直接进入正题. 一.异步处理 场景:发送手机验证码,邮件 传统古老处理方式如下图 这个流程,全部在主线程完成,注册->入库->发送邮件->发送短信,由于都在主线程,所以要等待每一步完 ...

  5. RabbitMq应用一

    RabbitMq应用一 RabbitMQ的具体概念,百度百科一下,我这里说一下我的理解,如果有少或者不对的地方,欢迎纠正和补充. 一个项目架构,小的时候,一般都是传统的单一网站系统,或者项目,三层架构 ...

  6. 缓存、队列(Memcached、redis、RabbitMQ)

    本章内容: Memcached 简介.安装.使用 Python 操作 Memcached 天生支持集群 redis 简介.安装.使用.实例 Python 操作 Redis String.Hash.Li ...

  7. 消息队列性能对比——ActiveMQ、RabbitMQ与ZeroMQ(译文)

    Dissecting Message Queues 概述: 我花了一些时间解剖各种库执行分布式消息.在这个分析中,我看了几个不同的方面,包括API特性,易于部署和维护,以及性能质量..消息队列已经被分 ...

  8. windows下 安装 rabbitMQ 及操作常用命令

    rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.它遵循Mozilla Public License开源协议,采用 Erlang 实现的工业级的消息队列(MQ)服务器,Rab ...

  9. RabbitMQ + PHP (三)案例演示

    今天用一个简单的案例来实现 RabbitMQ + PHP 这个消息队列的运行机制. 主要分为两个部分: 第一:发送者(publisher) 第二:消费者(consumer) (一)生产者 (创建一个r ...

  10. RabbitMQ + PHP (二)AMQP拓展安装

    上篇说到了 RabbitMQ 的安装. 这次要在讲案例之前,需要安装PHP的AMQP扩展.不然可能会报以下两个错误. 1.Fatal error: Class 'AMQPConnection' not ...

随机推荐

  1. go channel

    channel 是go语言中不同goroutine之间通信一种方法 //定义一个channel c := make(chan bool) //向channel中写入 c <- true //读取 ...

  2. redis分片

    本文是在window环境下测试 什么是分片 当数据量大的时候,把数据分散存入多个数据库中,减少单节点的连接压力,实现海量数据存储 那么当多个请求来取数据时,如何知道数据在哪个redis呢,redis有 ...

  3. Jmeter学习笔记ONE

    最近想学一些关于性能测试方面的知识,其实之前已经初步了解了Jmeter工具,它是一个轻量级的性能测试工具,开源并且免费,相比于Loadrunner来说用起来更简便. JMeter 可以用于对服务器.网 ...

  4. poj2217

    Secretary Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1257   Accepted: 515 Descript ...

  5. 冰冻三尺非一日之寒--web框架Django(翻页、cookie)

    第二十一章 cookie 1.获取Cookie: request.COOKIES['key'] request.get_signed_cookie(key, default=RAISE_ERROR, ...

  6. css-css权威指南学习笔记8

    第十二章 列表与生成内容 1.list-style-type:cjk-ideographic生成一二三四的序号 2.不管是ul还是ol,list-style-type无法识别的值都应用为decimal ...

  7. Javascript格式化json返回的时间(/Date(1482747413000)/)

    //时间处理,类似/Date(1482747413000)/的形式,得到xxx年xx月xx日 11:11:11 function ChangeDateFormat(jsondate) { jsonda ...

  8. django缓存优化中caches参数如何配置?

    在python开发中,如果运营django进行编写,为了提升效率,常常需要优化缓存,缓存优化中必须掌握的caches参数相关知识: CACHES 配置参数概述 - 格式 CACHES 字典配置格式如下 ...

  9. centos 安装lnmp

    1:查看环境 cat /etc/redhat-release 2:关闭防火墙 chkconfig iptables off 3:配置CentOS 6.0 第三方yum源(CentOS默认的标准源里没有 ...

  10. POJ 2186 Popular Cows(Targin缩点)

    传送门 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 31808   Accepted: 1292 ...