RabbitMQ基本用法

  • 进程queue用于同一父进程创建的子进程间的通信
  • 而RabbitMQ可以在不同父进程间通信(例如在word和QQ间通信)

示例代码

  • 生产端(发送)
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
#相当于建立一个socket,连接本地的RabbitMQ,默认端口:5672
channel = connection.channel()#声明一个通信管道(信道) #在管道里什么一个queue
channel.queue_declare(queue='hello')#声明一个名称为hello的queue
#通过管道发送消息
channel.basic_publish(exchange='',
routing_key='hello',#queue的名字
body='Hellow Word!')#消息主体
connection.close()#关闭连接
  • 消费端(接收)
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
#不确定生产端或消费端谁先运行,因此为了避免错误,消费端也要申请一个queue
#消费端先运行,如果没申请这个queue,生产端还没建立这个queue,因此报错
channel.queue_declare(queue='hello') def callback(ch,method,properties,body):
#ch,管道(信道)channel的内存地址
#method,设置的一些基本信息
#properties,
#body,消息主体,二进制数据
print(ch,method,properties)
print('[x] Received %r'%body) #声明要收消息
channel.basic_consume(
callback,#如果收到消息就调用回调函数处理消息
queue='hello',#queue的名字
no_ack=True#不确认,是否处理完callback,给rabbitmq返回确认信息
)
#开始收消息
channel.start_consuming()#开启后一直收消息,没消息则卡住

消息分发

RabbitMQ消息分发(一对多)

  • 一个生产者,多个消费者
  • 多个消费者时,是轮询机制,依次分发给消费者。(每个消费者按顺序依次消费)

no_act设置是否确认消息处理完

  • 设置no_act = True,消费者不发送确认信息,RabbitMQ从发送消息队列后,不管消费者是否处理完,删除queue
  • 设置no_act = False,RabbitMQ等待消费者的callback处理完,发送确认信息,如果此时消费者down了,则Rabbit把消息轮询发送给下一个消费者,等待确认才会删除queue
  • 去掉no_act = True(默认为False),需要在回调函数中新增代码,手动向RabbitMQ发送确认信息
  • ch.basic_ack(delivery_tag=method.delivery_tag)

消息持久化

rabbitmq目录下启动cmd,命令:rabbitmqctl.bat list_queues查看当前queue列表

当我们需要消息不会丢失(RabbitMQ server宕机时),需要进行消息持久化

  • 1、在申明队列是加上参数使其持久化,生产者和消费者都需要申明
  • channel.queue_declare(queue='hello',durable=True)队列持久化
  • 2、在生产端发送消息函数时加入参数使消息持久化
  • 消息持久化
channel.basic_publish(
exchange='',
routing_key='hello',#queue的名字
body='Hellow Word!'
porperties=pika.BasicProperties(
delivery_mode=2#使队列里的消息持久化

)#消息主体

广播模式

消息公平分发

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

  • 在消费端channel.basic_consume()函数前新增一条代码
  • channel.basic_qos(prefetch_count=1)
  • 解释:如果有2个消费者(a,b),a处理消息比较慢,b比较快;RabbitMQ是轮询发送消息,依次给a一条,给b一条,再给a.....。当在消费者端设置以上代码时,a还在处理,那么RabbitMQ不会给a发送,只会给b

广播模式(消息是实时的,发送时没有启动接收端,消息丢失)

  • 1、发送端将消息发送到RabbitMQ的消息转发器(exchange)
  • 2、转发器(Exchange)遍历所有绑定它的queue,将消息广播给queue
  • 3、接收端从queue里获取接收消息
  • 4、使用此queue的消费者断开后,此queue删除

  • 设置exchange转发器
  • Exchange在定义的时候是有类型的,以决定到底是哪些Queue符合条件,可以接收消息
  • fanout: 所有bind到此exchange的queue都可以接收消息
  • direct: 通过routingKey和exchange决定的那个唯一的queue可以接收消息
  • topic:所有符合routingKey(此时可以是一个表达式)的routingKey所bind的queue可以接收消息

给所有bind此exchange的发送消息

  • 发送端
import pika
import sys connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.exchange_declare(exchange='logs',
type='fanout')#广播模式,不用申明queue指定queue名
#设置exchange为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()
  • 接收端
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
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#拿到这个随机分配的queue名
channel.queue_bind(exchange='logs',#绑定发送端的exchange
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 type=direct)

  • 生产者
import pika
import sys connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
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,
body=message)
print(" [x] Sent %r:%r" % (severity, message))
connection.close()
  • 消费者
import pika
import sys connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
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:
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,
no_ack=True) channel.start_consuming()

细致的消息过滤()

  • 生产者
import pika
import sys connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
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()
  • 消费者
  • 参数为#,不过滤收所有
  • mysql.*,收所有mysql开头的消息
import pika
import sys connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
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,
no_ack=True) channel.start_consuming()

RabbitMQ基本用法、消息分发模式、消息持久化、广播模式的更多相关文章

  1. RocketMQ 原理:消息存储、高可用、消息重试、消息幂等性

    目录 消息存储 消息存储方式 非持久化 持久化 消息存储介质 消息存储与读写方式 消息存储结构 刷盘机制 同步刷盘 异步刷盘 小结 高可用 高可用实现 主从复制 负载均衡 消息重试 顺序消息重试 无序 ...

  2. 工作队列work queues 公平分发(fair dispatch) And 消息应答与消息持久化

    生产者 package cn.wh.work; import cn.wh.util.RabbitMqConnectionUtil; import com.rabbitmq.client.Channel ...

  3. (六)RabbitMQ消息队列-消息任务分发与消息ACK确认机制(PHP版)

    原文:(六)RabbitMQ消息队列-消息任务分发与消息ACK确认机制(PHP版) 在前面一章介绍了在PHP中如何使用RabbitMQ,至此入门的的部分就完成了,我们内心中一定还有很多疑问:如果多个消 ...

  4. rabbitmq消息队列,消息发送失败,消息持久化,消费者处理失败相关

    转:https://blog.csdn.net/u014373554/article/details/92686063 项目是使用springboot项目开发的,前是代码实现,后面有分析发送消息失败. ...

  5. RabbitMQ消息队列(六)-消息任务分发与消息ACK确认机制(.Net Core版)

    在前面一章介绍了在.Net Core中如何使用RabbitMQ,至此入门的的部分就完成了,我们内心中一定还有很多疑问:如果多个消费者消费同一个队列怎么办?如果这几个消费者分任务的权重不同怎么办?怎么把 ...

  6. 轻松搞定RabbitMQ(三)——消息应答与消息持久化

    转自 http://blog.csdn.net/xiaoxian8023/article/details/48710653 这个官网的第二个例子中的消息应答和消息持久化部分.我把它摘出来作为单独的一块 ...

  7. Spring Boot 之 RabbitMQ 消息队列中间件的三种模式

    开门见山(文末附有消息队列的几个基本概念) 1.直接模式( Direct)模式 直白的说就是一对一,生产者对应唯一的消费者(当然同一个消费者可以开启多个服务). 虽然使用了自带的交换器(Exchang ...

  8. Kafka分片存储、消息分发和持久化机制

    Kafka 分片存储机制 Broker:消息中间件处理结点,一个 Kafka 节点就是一个 broker,多个 broker 可以组成一个 Kafka集群. Topic:一类消息,例如 page vi ...

  9. RabbitMQ原理与相关操作(三)消息持久化

    现在聊一下RabbitMQ消息持久化: 问题及方案描述 1.当有多个消费者同时收取消息,且每个消费者在接收消息的同时,还要处理其它的事情,且会消耗很长的时间.在此过程中可能会出现一些意外,比如消息接收 ...

随机推荐

  1. Flume启动时报错Caused by: java.lang.InterruptedException: Timed out before HDFS call was made. Your hdfs.callTimeout might be set too low or HDFS calls are taking too long.解决办法(图文详解)

    前期博客 Flume自定义拦截器(Interceptors)或自带拦截器时的一些经验技巧总结(图文详解) 问题详情 -- ::, (agent-shutdown-hook) [INFO - org.a ...

  2. HDU6301 Distinct Values (多校第一场1004) (贪心)

    Distinct Values Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  3. 勤哲excel服务器WEB网页环境搭建问题解决

    因为客户希望在浏览器上使用勤哲的功能,因此希望大家勤哲excel服务器的web环境. 他们用的是勤哲2010版,需要装到64位环境下.在搭建的时候,遇到2个主要问题. 问题1:编译器错误消息: BC3 ...

  4. java 简单封装resultMap返回对象为map

    public class DbUtils { private static String host = "47.93.******"; private static String ...

  5. I2C(smbus pmbus)和SPI分析

    2C和SPI作为两种非常常用的低速外部总线 I2C I2C是以前的飞利浦半导体制定的标准,也就是如今的NXP. I2C总线由一条数据线(SDA)和一条时钟线(SCL)组成.设备分主从,主设备提供时钟, ...

  6. SQL语句 ANSI_NULLS 值(ON|OFF)的含义

    官方说明: 1.当 SET ANSI_NULLS 为 ON 时,即使 column_name 中包含空值,使用 WHERE column_name = NULL 的 SELECT 语句仍返回零行. 即 ...

  7. linux 的 sftp 和 scp

    ====================================== 作者: wxy0327(http://wxy0327.itpub.net) 发表于: 2006.12.07 13:19 分 ...

  8. js中url有中文的转码方法

    转载:https://www.cnblogs.com/chiangfai/p/6073000.html

  9. 原生JS实现图片拖拽移动与缩放

    看一下最终效果,图片可以拖动,可以缩放 把代码贴出来,可以直接粘贴使用,大致的思想就是鼠标按下的时候获取当时的鼠标位置,要减去left和top值,移动的时候获取位置减去初始的值就得到移动的时候的lef ...

  10. java——保存书店每日交易记录程序设计

    Books.java: 这个文件定义了一个Books类. 规定Books类拥有的属性:int id, String name, String publish, double price, int nu ...