参考:http://rabbitmq.mr-ping.com/AMQP/AMQP_0-9-1_Model_Explained.html

简答模式(exchange不工作)

import pika

# 链接
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost')) channel = connection.channel() # 建立通道
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() # 启动消费者

消费者

import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.queue_declare(queue='hello') # 生成队列,并命名为hello channel.basic_publish(exchange='', # 不设置交换机
routing_key='hello', #将设置传入的消息的队列
body='Hello World!') # 传入数据
print(" [x] Sent 'Hello World!'")
connection.close() # 关闭链接

生产者

Exchange模型1——简单分发

绑定的路由键(routing key)名称与队列名称相同。

发布订阅和简单的消息队列区别在于,发布订阅会将消息发送给所有的订阅者,而消息队列中的数据被消费一次便消失。所以,RabbitMQ实现发布和订阅时,会为每一个订阅者创建一个队列,而发布者发布消息时,会将消息放置在所有相关队列中。

import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.exchange_declare(exchange='logs',
type='fanout') # 这里type 是fanout message = "info: Hello World!"
channel.basic_publish(exchange='exchanger_name', # exchange要设置一个名称
routing_key='', # 不设置具体的通道,让交换机决定
body=message)
print(" [x] Sent %r" % message)
connection.close()

生产者

import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.exchange_declare(exchange='exchanger_name',
type='fanout') result = channel.queue_declare(exclusive=True) # 这里队列并不指定名称
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, # 这里用随机的名字
no_ack=True) # 无应答模式 channel.start_consuming()

消费者

exchange模型2——关键字

直连交换机经常用来循环分发任务给多个工作者(workers),消息的负载均衡是发生在消费者(consumer)之间的,而不是队列(queue)之间。

关键词的是由消费者决定的,循环完成绑定

import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.exchange_declare(exchange='direct_logs',
type='direct') # 这里type=direct 代表关键字分发模式 severity = "abc"
message = "hello world"
channel.basic_publish(exchange='direct_logs',
routing_key=severity, # 设置分发的关键字"abc"
body=message)
print(" [x] Sent %r:%r" % (severity, message))
connection.close()

生产者

#!/usr/bin/env python
import pika connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.exchange_declare(exchange='direct_logs',
type='direct') # 这里 type = “direct” result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue severities = ["abc","bcd","awd"] # 三个关键字 for severity in severities:
channel.queue_bind(exchange='direct_logs',
queue=queue_name,
routing_key=severity) # 用这三个关键字设置为routing_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,
no_ack=True) channel.start_consuming()

消费者

exchange模型3——模糊关键词

关键用点分割*代表匹配一个词,#代表多个关键词

new.age.rabbit          new.*  -- 不匹配 
new.age.rabbit          new.#  -- 匹配
new.age.rabbit          #.rabbit  -- 匹配
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.exchange_declare(exchange='topic_logs',
type='topic') # 这里是topic result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue binding_keys = ["abc","cba","bac"] # 设置三个路径 for binding_key in binding_keys: # 循环三次为queue_name这个队列绑定三个关键词
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,
no_ack=True) channel.start_consuming()

消费者

import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.exchange_declare(exchange='topic_logs',
type='topic') routing_key = "#.bca" # 模糊关键词
message = 'Hello World!'
channel.basic_publish(exchange='topic_logs',
routing_key=routing_key,
body=message)
print(" [x] Sent %r:%r" % (routing_key, message))
connection.close()

生产者

exchange模型4——头

有时消息的路由操作会涉及到多个属性,此时使用消息头就比用路由键更容易表达,头交换机(headers exchange)就是为此而生的。头交换机使用多个消息属性来代替路由键建立路由规则。通过判断消息头的值能否与指定的绑定相匹配来确立路由规则。

参数

拿取顺序

默认消息队列里的数据是按照顺序被消费者拿走,例如:消费者1 去队列中获取 奇数 序列的任务,消费者1去队列中获取 偶数 序列的任务。(问题是有可能其中一个消费者处理慢,依然造成排队)

channel.basic_qos(prefetch_count=1) 表示谁来谁取,不再按照奇偶数排列。这个参数放在消费者代码部分

持久化:durable

顾名思义,防止数据丢失,但会降低效率

import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(host='10.211.55.4'))
channel = connection.channel() # make message persistent
channel.queue_declare(queue='hello', durable=True) # 生产者持久化参数 channel.basic_publish(exchange='',
routing_key='hello',
body='Hello World!',
properties=pika.BasicProperties(
delivery_mode=2, # make message persistent
))
print(" [x] Sent 'Hello World!'")
connection.close() # 消费者
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pika connection = pika.BlockingConnection(pika.ConnectionParameters(host='10.211.55.4'))
channel = connection.channel() # make message persistent
channel.queue_declare(queue='hello', durable=True) # 消费者持久化参数 def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
import time
time.sleep(10)
print 'ok'
ch.basic_ack(delivery_tag = method.delivery_tag) channel.basic_consume(callback,
queue='hello',
no_ack=False) print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

持久化

应答模式: no-ack

当一个消息从队列中投递给消费者后(consumer),消费者会通知一下消息代理(broker),这个可以是自动的也可以由处理消息的应用的开发者执行。当“消息确认”被启用的时候,消息代理不会完全将消息从队列中删除,直到它收到来自消费者的确认回执(acknowledgement)。

import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
host='10.211.55.4'))
channel = connection.channel() channel.queue_declare(queue='hello') def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
import time
time.sleep(10)
print 'ok'
ch.basic_ack(delivery_tag = method.delivery_tag) channel.basic_consume(callback,
queue='hello',
no_ack=False) # 这里写false 代表会应答 print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

消费者

Exclusive:

只被一个连接(connection)使用,而且当连接关闭后队列即被删除

RPC模式

RPC(Remote Procedure Call)—远程过程调用

通俗的讲:两台电脑A,B,A计算机需要用到B的方法或者函数,由于不共享内存,需要通过通信来传递命令和相关数据。

import pika

# 建立连接,服务器地址为localhost,可指定ip地址
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost')) # 建立会话
channel = connection.channel() # 声明RPC请求队列
channel.queue_declare(queue='rpc_queue') # 数据处理方法
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2) # 对RPC请求队列中的请求进行处理
def on_request(ch, method, props, body):
n = int(body) print(" [.] fib(%s)" % n) # 调用数据处理方法
response = fib(n) # 将处理结果(响应)发送到回调队列,这里用简单模式
ch.basic_publish(exchange='',
routing_key=props.reply_to, # 这里拿到生产者的这个参数作为返回队列的名字
properties=pika.BasicProperties(correlation_id = \
props.correlation_id), # 这里拿到请求的唯一id作为标识并返回,方便生产者确认
body=str(response))
ch.basic_ack(delivery_tag = method.delivery_tag) # 负载均衡,同一时刻发送给该服务器的请求不超过一个
channel.basic_qos(prefetch_count=1) channel.basic_consume(on_request, queue='rpc_queue') print(" [x] Awaiting RPC requests")
channel.start_consuming()

消费者,最初队列的建立者

import pika
import uuid class FibonacciRpcClient(object):
def __init__(self):
”“”
客户端启动时,创建回调队列,会开启会话用于发送RPC请求以及接受响应 “”“ # 建立连接,指定服务器的ip地址
self.connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost')) # 建立一个会话,每个channel代表一个会话任务
self.channel = self.connection.channel() # 声明回调队列,再次声明的原因是,服务器和客户端可能先后开启,该声明是幂等的,多次声明,但只生效一次
result = self.channel.queue_declare(exclusive=True)
# 将次队列指定为当前客户端的回调队列
self.callback_queue = result.method.queue # 客户端订阅回调队列,当回调队列中有响应时,调用`on_response`方法对响应进行处理;
self.channel.basic_consume(self.on_response, no_ack=True,
queue=self.callback_queue) # 对回调队列中的响应进行处理的函数
def on_response(self, ch, method, props, body):
if self.corr_id == props.correlation_id: # 如果验证码通过,就拿到结果对response赋值
self.response = body # 发出RPC请求
def call(self, n): # 初始化 response
self.response = None #生成correlation_id
self.corr_id = str(uuid.uuid4()) # 生成每个任务的id # 发送RPC请求内容到RPC请求队列`rpc_queue`,同时发送的还有`reply_to`和`correlation_id`
self.channel.basic_publish(exchange='',
routing_key='rpc_queue', # 队列名字叫rpc_queue
properties=pika.BasicProperties(
reply_to = self.callback_queue, # 把回调的队列的名字传进来
correlation_id = self.corr_id, #这是唯一id
),
body=str(n)) # 传数据 while self.response is None:
self.connection.process_data_events() # 如果没有返回值,就一直阻塞等着callback队列的
return int(self.response) # 建立客户端
fibonacci_rpc = FibonacciRpcClient() # 发送RPC请求
print(" [x] Requesting fib(30)")
response = fibonacci_rpc.call(30) # 这里发起传递
print(" [.] Got %r" % response)

生产者,生产了回调通道

其他及补充:

  • Auto-delete (当所有与之绑定的消息队列都完成了对此交换机的使用后,删掉它)
  • Arguments(依赖代理本身)

消费者模型

  消息如果只是存储在队列里是没有任何用处的。被应用消费掉,消息的价值才能够体现。在AMQP 0-9-1 模型中,有两种途径可以达到此目的:

  • 将消息投递给应用 ("push API")
  • 应用根据需要主动获取消息 ("pull API")

  使用push API,应用(application)需要明确表示出它在某个特定队列里所感兴趣的,想要消费的消息。如是,我们可以说应用注册了一个消费者,或者说订阅了一个队列。一个队列可以注册多个消费者,也可以注册一个独享的消费者(当独享消费者存在时,其他消费者即被排除在外)。

  每个消费者(订阅者)都有一个叫做消费者标签的标识符。它可以被用来退订消息。消费者标签实际上是一个字符串。

消息的属性

    • Content type(内容类型)
    • Content encoding(内容编码)
    • Routing key(路由键)
    • Delivery mode (persistent or not)
      投递模式(持久化 或 非持久化)
    • Message priority(消息优先权)
    • Message publishing timestamp(消息发布的时间戳)
    • Expiration period(消息有效期)
    • Publisher application id(发布应用的ID)

Rabbit mq 简单应用的更多相关文章

  1. 在 Windows 上安装Rabbit MQ 指南

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

  2. (转)在 Windows 上安装Rabbit MQ 指南

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

  3. celery rabbit mq 详解

    Celery介绍和基本使用 Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, ...

  4. Rabbit MQ 消息确认和持久化机制

    一:确认种类 RabbitMQ的消息确认有两种.一种是消息发送确认,用来确认生产者将消息发送给交换器,交换器传递给队列的过程中消息是否成功投递.发送确认分为两步,一是确认是否到达交换器,二是确认是否到 ...

  5. Rabbit MQ 入门指南

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

  6. 分布式消息中间件Rabbit Mq的了解与使用

    MQ(消息队列)作为现代比较流行的技术,在互联网应用平台中作为中间件,主要解决了应用解耦.异步通信.流量削锋.服务总线等问题,为实现高并发.高可用.高伸缩的企业应用提供了条件. 目前市面比较流行的消息 ...

  7. Spring Boot:使用Rabbit MQ消息队列

    综合概述 消息队列 消息队列就是一个消息的链表,可以把消息看作一个记录,具有特定的格式以及特定的优先级.对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息,对消息队列有读权限的进程则可以 ...

  8. Spring boot集成Rabbit MQ使用初体验

    Spring boot集成Rabbit MQ使用初体验 1.rabbit mq基本特性 首先介绍一下rabbitMQ的几个特性 Asynchronous Messaging Supports mult ...

  9. Rabbit MQ 学习参考

    网上的教程虽然多,但是提供demo的比较少,或者没有详细的说明,因此,本人就照着网上的教程做了几个demo,并把代码托管在码云,供有需要的参考. 项目地址:https://gitee.com/dhcl ...

随机推荐

  1. jsonp原理及同源策略

    [个人学习笔记,如有问题还请前辈纠正] jsonp 是用来跨域读取数据的,为什么从不同的域访问数据要用jsop呢?这源于一个著名的安全策略--同源策略,即: 协议.端口号.域名相同 举例说明:http ...

  2. java的环境配置

    java的安装 1,进入官网  https://www.oracle.com/index.html 2.Menu -> Downloads -> java ->  all Java ...

  3. ORACLE中用户等系统信息操作

    1.查看所有用户:select * from dba_users;   select * from all_users;   select * from user_users; 2.查看用户或角色系统 ...

  4. [持续交付实践] pipeline使用:Multibranch Pipeline

    前言 在探讨multiBranch Pipeline之前,很有必要先探讨下如何制定有效的代码分支管理规范,使用高效的版本控制系统,并对构建产物及其依赖进行管理.我们首先要强调,需要进行版本控制的不仅是 ...

  5. layer.js 中弹框显示不全的问题

    在使用 layer.js 做弹框的时候,遇到在浏览器缩小时,弹框显示不全的问题,如下: 这是不行的,因为我们有的时候想缩小浏览器视窗,但是一旦缩小到一定程度,就会把弹窗的关闭按钮遮住一部分,并且主体弹 ...

  6. spring mvc返回json格式和json字符串

    首先有必要说一下,json和json字符串是不一样的,后者是一个字符串.而json是一个对象 当然如果调用位置是后台程序这几乎没有区别,因为在后台,无论什么格式数据,都是从响应流中读取字符串. 但是在 ...

  7. 机器学习linux系统环境安装

    机器学习linux系统环境安装 安装镜像下载 可以自己去ubuntu官方网站按照提示下载amd64的desktop版本 或者考虑到国内镜像站点下载,如tuna,163, ali等 课程使用最新的17. ...

  8. IOC 和DI(转载)

    IOC 是什么? Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内 ...

  9. Mysql连接数太多ERROR 1040 (HY000): Too many connections

    数据库连接报错:ERROR 1040 (HY000): Too many connections   1.查看连接数 /usr/local/mysql/bin/mysqladmin -h host - ...

  10. TPL DataFlow初探(一)

    属性TPL Dataflow是微软面向高并发应用而推出的一个类库.借助于异步消息传递与管道,它可以提供比线程池更好的控制,也比手工线程方式具备更好的性能.我们常常可以消息传递,生产-消费模式或Acto ...