RabbitMQ

本文深入讲解RabbitMQ的原理及应用,包括其基于AMQP协议的特性,如何将同步操作转为异步,实现系统解耦。探讨了RabbitMQ与其他消息队列如ActiveMQ、ZeroMQ的区别,以及其在高并发场景下的优势。通过实例演示了RabbitMQ的安装、配置和基本编程模式,如工作队列、发布订阅、路由模式等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RabbitMQ是由erlang语言开发,基于AMOP(Advanced Message Queue高级消息队列) 协议实现的消息队列,它是一种应用程序之间的通信发方法。
MQ的作用:
1把同步操作变成异步操作
2解耦合

AMOP协议:是一套专门公开的消息中间件的协议。
市场上还有哪些消息队列:
ActiveMQ RabbitMQ ZeroMQ Kalfaf MetaMQ RocketMQ Redis.
为什么使用RabbitMQ?
1 使用简单,文档完善
2 基于AMOP协议
3 社区活跃,文档完善
4 高并发性能好,这主要得益于Erlang语言
5 Spring Boot默认已经集成RabbitMQ

JMS:
java消息服务
java消息服务应用程序接口是一个java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。java消息服务与具体平台无关的API,绝大多数MOM厂商都对JMS提供支持。

RabbitMQ的工作原理:

在这里插入图片描述
大致流程:
由生产者Producer将消息通过交换机(Exchange)转发到Queue,消费者(Consumer)会监听队列(Queue)一旦有消息,就会去消费,如果消费者还没有能监听到Queue则Queue继续等待消费者(Consumer)来消费。

消息发布接受流程:
发送消息:
1 生产者和Broker建立TCP连接
2 生产者和Broker建立通道(会话通道)
3 生产者通过通道消息发送到Broler,有Exchange将消息进行转发
4 Exchange将消息发送到指定Queue(队列)

接受消息:
1 消费者和Broker建立TCP连接
2 消费者和Broker建立通道
3 消费者监听指定的Queue(队列)
4 当有消息到达Queue时Broker默认将消息推送给消费者
5 消费者接收到消息

安装RabbitMQ的下载:
1 先下载erlang语言环境
2 下载地址:http://www.rabbitmq.com/download.htl

在这里插入图片描述
下载安装与安装:
1 首先先安装erlang语言的环境:http://erlang.org/download/otp_win64_20.3.exe并配置环境变量。
2 安装RabbitMQ:https://github.com/rabbitmq/rabbitmq-server/releases/tag/v3.7.3
以管理员的方式在,sbin目录下安装管理插件:rabbitmq-plugins.bat enable rabbitmq_management

浏览器启动:http://localhost:15672
默认登录用户名和密码都是:guest

出现如下画面,则表示安装成功
在这里插入图片描述
注意事项:
当卸载RabbitMQ重新安装出现RabbitMQ服务注册失败,此时需要进入注册表清理erlang,搜索RabbitMQ. ErlSrv,将对应的项全部删除。

RabbitMQ入门程序:
1 生产者:
channel.queueDeclare()
这里面的参数的说明:
参数说明:
1 queue队列名称
2 durable 是否持久化,如果持久化,mq重启后队列
3 exclusive: 是否独占连接,队列只允许在连接访问,如果connection连接关闭队列自动删除,如果将此参数设置true可用于临时队列的创建
4 autoDelete自动删除,队列不再使用时是否自动删除此队列,如果将此参数和exclusive参数设置为true就可以实现临时队列(队列不用了就自动删除)
5 arguments参数,可以设置一个队列的扩展参数,比如:可设置存活时间.

//生产者代码:
   public class Producer{
   private static finally String quque="hello1"  //队列的名称
   public static void main(){
    //通过连接工厂创建新的连接和mq建立连接
    ConnectionFactory connectionFactory =new ConnectionFactory();
    connectionFactory.setHost("127.0.0.1");
    connectionFactory.setPort("5672");
    connectionFactory.setUsername("guest");
    connectionFactory.setPassword("guest");
    //设置虚拟机,一个mq服务可以设置多个虚拟机,每个虚拟机就相当于一个独立的mq
    connectionFactory.setVirtunaHost("/");
try{
 connection=connectionFactory.newConnection();
 //设置创建会话通道,生产者和mq服务所有的服务都在channel通道中完成
 Channel channel=connection.createChannel();
    //不用声明交换机默认有
    //声明队列,如果队列在mq中没有就创建一个
    channel.queueDeclare();
    //发送消息
    //参数说明:1 exchange:交换机设置为空(""),如果不指定将使用mq的默认交换机
    2 //rountingKey, 路由key,交换机根据路由Key来将消息转发到指定的队列,如果使用默认交换机,rountingKey设置为队列的名称
    3 //消息的属性 
    4//消息的信息
    channel.basicPublish("",QUEUE,null,message.getBytes());
}catch(){

}finally{
   //先关闭通道
   channel.close();
   //再关闭连接
   connection.close();
}
}
}

大致流程总结:
1 发送端操纵流程:
1)创建连接
2)创建通道
3声明队列
4)发送消息.

消费者:

//消费者
private static finally String quque="hello1"  //队列的名称
   public static void main(){
    //通过连接工厂创建新的连接和mq建立连接
    ConnectionFactory connectionFactory =new ConnectionFactory();
    connectionFactory.setHost("127.0.0.1");
    connectionFactory.setPort("5672");
    connectionFactory.setUsername("guest");
    connectionFactory.setPassword("guest");
    //设置虚拟机,一个mq服务可以设置多个虚拟机,每个虚拟机就相当于一个独立的mq
    connectionFactory.setVirtunaHost("/");
try{
 connection=connectionFactory.newConnection();
 //设置创建会话通道,生产者和mq服务所有的服务都在channel通道中完成
 Channel channel=connection.createChannel();
    //不用声明交换机默认有
    //声明队列,如果队列在mq中没有就创建一个
    channel.queueDeclare(QUEUE,true,false,false,null);
//实现消费方法
DefaultConsumer defaultConsumer=new DefaultConfumer(channel){
   //当接收到消息后此方法将被调用
   @Param ConsumerTag: 消费者标签,用来标识消费者的,在监听队列时设置channel,basicConsume
   @Param envelope: 信封,通过envelope,通过envelope可以在获取消息Id,mq在channel中用来标示消费的Id。
   public void handleDeliver(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body)throw IOException{
   //交换机
   String exchange=envelope.getExchange();
   //消息id,mq在channel中用来标识消费的Id,可用于确认消息已接收
   long deliverTag=envelope.getDeliveryTag();
   //消息内容
   String message=new String(body,""utf-8");
   System.out.println(message); //打印消息
}
}
//实现消费方
//监听队列
//参数:String queue, boolean autoAck,Consumer callback
 //参数明细:
   1 queue 队列名称
   2 autoAck 自动回复,当消费方接受到消息后要告诉mq消息已接收,如果将此参数设置为true表示自动回复mq,如果设置为false要通过编程实现回复
   3 callback:消费方法;当消费者接受到消息要执行的方法
 channel.basiConsume(QUEUE,true,defaultConsumer)

消费者不能关闭:因为消费者要不停的监听。

接收端:
1)创建连接
2)创建通道
3)声明队列
4)监听队列
5 )接受消息
6) ack回复(自动回复,如果设置了fasle就使用编程的方式写一个回复)

RabbitMQ工作模式:
(Work queues) 工作队列模式:
在这里插入图片描述

     一个生产者+一个队列+多个消费者
     它的特点:
         一个生产者将消息发给发给一个队列
         多个消费者共同监听一个队列的消息
         消息不能重复消费
         rabbit采用轮询的方式将消息是平均发送给消费者
        应用场景: 多个消费者协同来工作。

Publish/Subscribe:发布与订阅模式
在这里插入图片描述
特点:生产者发布一条消息,可以被多个消费者接收到。
案例:
用户通知,当用户充值成功或转账完成系统通知用户,通知方式有短信,邮件等多种方式.

//在之前的代码中,加入:
   新的变化:
      private static final String QUEUE_INFORM_EMAIL="queue_inform_email";
      private static final String QUEUE_INFORM_SMS="queue_inform_sms";
      private static final String EXCBANE_FANOUT_INFORM="exchange_fanout_inform"; //交换机的名字
//声明邮件队列
channel.queueDeclare(QUEUE_INFORM_EMAIL,true,false,false,null);
channel.queueDeclare(QUEUE_INFORM_SMS,true,fasle,false,null);
//声明交换机
交换机的工作模式有
参数:
 1 交换机的名称
 2 交换机的类型:
    1 交换机的名称
    2 交换机的类型
    3 fanout:对应的rabbitmq的工作模式是 publish/subscribe
    4 direct: 路由的工作模式
    5 通配符工作模式
    6 headers:对应的headers工作模式
    6 rpc远程调用
channel.exchangeDeclare(EXBANE_FANOUT_INFORM,BuiltinExchangeType.FANOUT);
进行交换机和队列绑定
//参数的明细: String queue,String exchange,String routingKey
 1 queue队列的名称 2 exchange 交换机名称  3 routingKey 路由key,作用是交换机根据路由key的值将消息转发到指定的队列中,在发布订阅模式中调协为空字符串
channel.queueBind(QUEUE_INFOREM_EMAIL,EXCHANGE_FANOUT_INFORM,"');
发布消息:
   for(int i=0;i<5;i++){
   //消息内容
   String message="send inform message to user";
   channel.basicPublish(EXCHANGE_FANOUT_INFORM,"",null,message.getBytes());
}

在这里插入图片描述

Routind路由模式:
可以通过指定路由的条件,来分发消息,它也可以实现发布与订阅模式。同时它的功能更加强大。
路由工作模式代码示例:

//由上面的代码加以修改即可,在声明上加上ROUTINGKEY(路由Key)
  private static final String ROUTINGKEY_EMAIL="inform_eamail";
  private static final String ROUNTINGKEY_SMS="inform_sms";
  //队列在绑定交换机的时候要指定对应的ROUNTKEY:
    channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANGE_ROUNTING_INFORM,ROUTINGKE_EMAIL);
channel.queueBind(QUEUE_INFORM_SMS,EXCHANGE_ROUNTING_INFORM,ROUNTINGKEY_SMS);
//声明交换机时,交换机的类型要改成DIRECT类型
channel.excahngeDeclare(EXCHANGE_ROUTING_INFORM,BuiltinExchangeType.DIRECT);
//发消息:在发消息的时候,需要指定ROUNTINGKEY
channel.basicPublish(EXCHANGE_ROUTING_INFORM,ROUNTINGKEY_EMAIL,null,message.getBytes());

在这里插入图片描述
Topics通配符模式:
通配符交换机的类型要设置成type=topic ,
通配符有哪些:
符号#:匹配一个或多个词,比如inform.#可以匹配inform.sms,inform.email,inform.email.sms
符号*:只能匹配一个词,比如:inform.* 可以匹配inform.sms,inform.email
案例:根据用户的通知设置去通知用户,有的用户
在这里插入图片描述
实列代码:

//在路由模式的基础上稍微做改变
private static final String ROUTINGKEY_EMAIL="inform.#.email.#"; //这个路由key可以匹配inform.email,也可以匹配inform.email.sms
private static final String ROUTINGKEY_SMS="inform.#.sms.#"; //可以匹配inform.email.sms,也可以匹配inform.sms
//绑定交换机和队列
//声明交换机
channel.exchangeDeclare(EXCHANGE_TOPICS_INFORM,BuiltingExchangeType.TOPIC);
channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANCE_TOPICS_INFORM,ROUTINGKEY_EMAIL);
channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANCE_TOPICS_INFORM,ROUTINGKEY_SMS);

发消息:

在这里插入图片描述
Header模式:
header模式与rounting不同的地方在于,head模式取消rountingkey,使用header的key/value(键值对)匹配队列

在这里插入图片描述
发送消息:

在这里插入图片描述
RPC模式:

在这里插入图片描述
SpringBoot整合RabbitMQ:
首先导入依赖:
在生产者和消费者分别加上下面的依赖:
在这里插入图片描述
添加配置文件:日志的文件和application.yml
application.yml内容是:
在这里插入图片描述
在RabbitMQ工程下,创建一个配置类,用来声明交换机,声明队列,绑定交换机和队列
代码示例如下:

在这里插入图片描述
绑定emil队列和交换机
在这里插入图片描述
生产端的代码:
使用rabbitTemplate发送消息:

在这里插入图片描述

消费端代码示例:
首先和生产者一样,创建一配置类,来声明队列交换机,并绑定队列和交换机
创建一个ReceiveHandler用来接收消息并处理,使用@RabbitListener注解监听队列:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_43557743

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值