RabbitMQ-消息队列 学习

什么是消息队列(MQ)

MQ全称为Message Queue 消息队列是一种应用程序对应用程序的通信方式(进程间通信)。MQ是消费-生产者模型的一个典型代表,一端往消息队列中不断写入消息,而另一端则可以读取队列中的消息。 它是脱离语言而存在的,php、Java、c++等语言都能够操作消息队列。

队列

队列是一种先入先出(FIFO)的数据结构

为什么要用消息队列

消息队列是分布式系统中重要的组件,主要解决应用解耦、异步消息、流量削峰等问题,实现高性能、高可用、可伸缩和最终一致性框架。目前使用较多的消息队列有ActiveMQ、RabbitMQ、ZeroMQ、Kafka、MetaMQ、RocketMQ。

RabbitMQ

RabbitMQ是一个由Erlang语言开发的AMQP的开源实现。 rabbitMQ是一款基于AMQP协议的中间件,它能够在应用之间提供可靠的消息传输。可以理解它是一个软件。

Windows开发必须先安装一下Erlang,就像玩《我的世界》需要安装java一样。

思路梳理:整套工作流程需要 生产者、RabbitMQ、消费者。RabbitMQ作为中间件,充当两者交流的桥梁,生产者发出消息而后消费者监听到消息并拿出来消费。

RabbitMQ的工作模型

在启动RabbitMQ的前提下执行代码

1. 简单模式(只有一个消费者

示意图:

生产者:

  1. 连接RabbitMQ
  2. 创建队列
  3. 向指定的队列插入数据

用python打比方:

 

python

代码解读

复制代码

# 1.连接RabbitMQ # 拿到 “连接对象” connection = xxx('localhost',5762,'guest','guest') #省略连接代码,不同语言找文档即可 channel = connection.channel() #拿到 “频道对象”,用它对RabbitMQ进行相关的控制 # 2.创建队列 channel.quere_declare(queue='queue_name') #指定队列的名称(唯一) # 3.向指定的队列插入数据 channel.basic_publish( exchange='', #交换机参数,简单模式不用填 routing_key='queue_name', #指定队列 body='Hello World!' #数据 ) connection.close() #关闭连接

消费者:

  1. 连接RabbitMQ
  2. 监听队列
  3. 确定回调函数

用python打比方:

 

python

代码解读

复制代码

# 1.连接RabbitMQ connection = xxx('localhost',5762,'guest','guest') #省略连接代码,不同语言找文档即可 channel = connection.channel() #拿到 “频道对象” # 2.创建队列 !! 不一定是生产者先运行,所以消费者也需要有创建队列的代码, # 如果该队列已创建,RabbitMQ会无视 channel.quere_declare(queue='queue_name') # 3.声明回调函数 def callback(ch,method,properties,body): print("[x] Received %r" % body) # 确定监听队列 (先确定了但还未真正监听,具体会根据不同语言不同库有不同表现,注意看文档) channel.basic_consume( queue = 'queue_name', auto_ack = True, #/默认应答(自动应答) on_message_callback = callback #绑定回调函数 ) # 开始消费 (真正开始监听,持续监听等待数据) channel.start_consuming()

参数使用
  1. 应答参数:

主要区别在消费者默认应答的模式为 当消费者取走队列中的数据后默认告诉RabbitMQ这个消息已经结束,但是万一在这个过程中出现了bug,那么数据就会丢失。因此开启手动应答:当消费者从队列中取出数据时,数据不会被删除,只有当程序在callback中的逻辑处理完全之后,再进行应答告诉RabbitMQ这个消息已结束,此时才会删除队列中的数据。

 

python

代码解读

复制代码

# 声明回调函数(手动应答) def callback(ch,method,properties,body): print("[x] Received %r" % body) ch.basic_ack(delivery_tag=method.delivery_tag) # 我目前看了三种语言都用ack做为应答 # 确定监听队列 channel.basic_consume( queue = 'queue_name', auto_ack = False, #True为默认应答(自动应答),False为手动应答 on_message_callback = callback )

  1. 持久化参数:

当队列中有数据未被处理,而此时服务器崩了,那么原本存在服务器内存中的(队列中的)数据就会消失掉。为了防止因服务器崩塌而导致的数据丢失问题,我们需要将数据持久化(存到磁盘中)。

需要在创建队列时赋予它代表持久化的参数。

 

python

代码解读

复制代码

# 创建可持久化队列 <若队列已被声明过,无法再变更为持久模式,必须重新命名> # 消费者那边声明的队列也必须加durable=True,才能接收到持久化的数据 channel.quere_declare(queue='queue_name_durable',durable=True) # 向可持久化队列 插入 可持久化数据<是可以插入不持久化数据的> channel.basic_publish( exchange='', routing_key='queue_name_durable', body='Hello World!', properties=pika.BasicProperties( #python的pika库的写法 delivery_mode = 2 #将属性delivery_mode设置为2则代表这条数据为可持久化 ) )

2. 交换机模式(可以有多个消费者

示意图:

生产者:

  1. 连接RabbitMQ
  2. 创建交换机
  3. 向指定的交换机插入数据

消费者:

  1. 连接RabbitMQ
  2. 创建队列(消费者必须自己创建队列,因为生产者不会创建了)
  3. 让队列绑定一个指定的交换机(绑定动作很重要)
  4. 确定回调函数

当生产者向交换机发送消息时,只要绑定了该交换机的队列都会拿到数据(人手一份)。

2.1 发布订阅模式
 

python

代码解读

复制代码

#生产者 # 1. 连接RabbitMQ connection = xxx('localhost',5762,'guest','guest') #省略连接代码,不同语言找文档即可 channel = connection.channel() #拿到 “频道对象” # 2. 创建交换机 指定交换机的名称(唯一),exchange_type='fanout' 为发布订阅模式 channel.exchange_declare( queue='exchange_name', exchange_type='fanout' ) # 3. 向指定的队列插入数据 channel.basic_publish( exchange='exchange_name', #交换机参数,填交换机名称 routing_key='', #不需要指定队列,所以这个为空,后续会有其他作用 body='Hello World!' #数据 ) connection.close() #关闭连接

 

python

代码解读

复制代码

#消费者 # 1. 连接RabbitMQ connection = xxx('localhost',5762,'guest','guest') #省略连接代码,不同语言找文档即可 channel = connection.channel() #拿到 “频道对象” # 创建交换机 !! 由于无法确定一定是生产者先启动,所以消费者也需要有创建交换机 # 的代码,内容需要与生产者一致,若已创建RabbitMQ会直接无视这代码 不用怕重复创建 channel.exchange_declare( queue='exchange_name', exchange_type='fanout' ) # 2. 创建队列 下方第一个参数为队列名,我们置空,将exclusive设为True # 系统就会自动给一个随机且唯一的名字,并且在返回值中可以拿到 result = channel.queue_declare("",exclusive=True) queue_name = result.method.queue #拿到系统生成的队列名 # 3. 将队列绑定到交换机 channel.queue_bind(exchange='exchange_name',queue=queue_name) # 4. 声明回调函数 def callback(ch,method,properties,body): print("[x] Received %r" % body) # 确定监听队列 (先确定了但还未真正监听,具体会根据不同语言不同库有不同表现,注意看文档) channel.basic_consume( queue = queue_name, auto_ack = True, #默认应答(自动应答) on_message_callback = callback #绑定回调函数 ) # 开始消费 (真正开始监听,持续监听等待数据) channel.start_consuming()

2.2 关键字模式

有一些情况,生产者插入到交换机的消息,并不一定是所有队列都需要的,可能指向让其中某几个消费者去消费。 那么需要在队列绑定交换机的时候加上关键字生产者发送消息的时候也带上关键字,就可以做到专门队列处理专门消息。

例如在“日志”中会常用来分类。

 

python

代码解读

复制代码

# 生产者 与发布订阅模式的区别 # 创建交换机 exchange_type='direct' 为关键字模式 channel.exchange_declare( queue='direct_exchange_name', exchange_type='direct' ) # 向指定的队列插入数据 channel.basic_publish( exchange='direct_exchange_name', #交换机参数,填交换机名称 routing_key='key1', #用于指定“关键字”,那么绑定了关键字key1的消费者可以收到消息 body='Hello World!' #数据 )

 

python

代码解读

复制代码

# 消费者 与发布订阅模式的区别 # 创建交换机 exchange_type='direct' 为关键字模式 channel.exchange_declare( queue='direct_exchange_name', exchange_type='direct' ) # 将指定队列绑定到交换机上 关键字需要加一个字段routing_key channel.queue_bind(exchange='direct_exchange_name',queue=queue_name,routing_key='key1') # 如果想绑定多个关键字,需要多写几次 一般用for循环做,这里直接演示 channel.queue_bind(exchange='direct_exchange_name',queue=queue_name,routing_key='key2') channel.queue_bind(exchange='direct_exchange_name',queue=queue_name,routing_key='key3')

2.3 通配符(模糊匹配)模式

关键字模式我们可以理解为,精准匹配模式,也就是生产者和消费者的关键字必须是完全一致才可以匹配到消息。如果我们需要进行模糊匹配可以使用通配符:

这种交换机我们也叫“通配符交换机”(Topic Exchange),在这里只有两种符号,符号“#”可匹配一个或多个词、符号“*”仅匹配一个词。可以进行大分类。

 

python

代码解读

复制代码

# 生产者 # 创建交换机 exchange_type='topic' 为通配符模式 channel.exchange_declare( queue='topic_exchange_name', exchange_type='topic' ) # 向指定的队列插入数据 channel.basic_publish( exchange='topic_exchange_name', #交换机参数,填交换机名称 routing_key='key666', #用于指定“关键字”,那么绑定了关键字key1的消费者可以收到消息 body='Hello World666!' #数据 )

 

python

代码解读

复制代码

# 消费者 # 创建交换机 exchange_type='topic' 为通配符模式 channel.exchange_declare( queue='topic_exchange_name', exchange_type='topic' ) # 将指定队列绑定到交换机上 模糊匹配的routing_key key# 就可以模糊匹配key1 key2等 channel.queue_bind(exchange='topic_exchange_name',queue=queue_name,routing_key='key#')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值