RabbitMQ入门学习

一、消息队列学习

MQ是一个互联网架构中常见的解耦利器。
什么时候不使用MQ?
上游实时关注执行结果
什么时候使用MQ?
1)数据驱动的任务依赖,多个任务需要轮流执行,轮流订阅上一个任务。
2)上游不关心多下游执行结果,上游执行完发送到MQ,多下游订阅MQ。
3)异步返回执行时间长
这里写图片描述
死信队列多了一个过期的机制,到期会自动去尝试消费,通过死信交换机做匹配,选择想要的消费失败的消息。
https://ke.qq.com/course/288116#term_id=100341172 入门视频
消息中间件是在消息传输过程中保存消息的容器。队列的主要目的是提供路由并保证消息的传递。
特点
1异步处理模式
2多个应用程序调用关系为松耦合关系
传递模型:
1、点多点模型PTP
每个消息只用一个消费者
发送者和接收者没有时间依赖
接受者确认消息接受和处理成功
2、发布-订阅模型Pub/Sub
一对多关系,通过订阅主题,发布者建立一个订阅,订阅者保持持续的活动状态以接收消息。
每个消息可以有多个订阅者
客户端只有订阅后才能接收到消息,有时间依赖。
持久订阅 订阅关系建立后,消息不会消失,不管订阅者是否都在线
非持久订阅 订阅者为了接受消息,必须一直在线

典型的应用案例
1、注册时发送邮件或发送短信
2、日志分析使用,多个服务产生的数据发送到中间件发送到分析服务。
3、消息复制,用于跨机房数据传输、搜索、离线数据计算等。
4、延迟消息发送和暂存,把中间件当成可靠的消息暂存地。接受消息,暂时先不发送。

二、RabbitMQ的安装

一、安装erlang,环境变量配置
这里写图片描述
这里写图片描述
输入erl –version查看安装是否成功。

二、rabbitMQ的安装
下载exe,安装。cd到其sbin目录。
这里写图片描述
执行插件命令rabbitmq-plugins enable rabbitmq_management 开启管理后台的插件
这里写图片描述

执行开启服务命令rabbitmq-server start
这里写图片描述
登录浏览器后台http://localhost:15672 账号和密码都是guest,添加用户、vhost、授权
https://blog.csdn.net/qq_33382113/article/details/78853680 资料

三、JAVA操作队列

连接工具,配置信息
这里写图片描述
1、简单队列
此时为匿名发送,不指定交换机,则直接发送到队列中。
这里写图片描述
这里写图片描述
这里写图片描述
2、工作队列WorkQueue
模型(消息轮流被多个消费者消费)
这里写图片描述
此时有两个消费者同时监听一个的队列。
其中一个线程sleep2秒,另一个消费者线程sleep1秒,但是处理的消息是一样多。
这种方式叫轮询分发(round-robin)不管谁忙,都不会多给消息,总是你一个我一个。

想要做到公平分发(fair dispatch),必须关闭自动应答ack,改成手动应答。
使用basicQos(perfetch=1)限制每次只发送不超过1条消息到同一个消费者,消费者必须手动反馈告知队列,才会发送下一个。
这里写图片描述
这里写图片描述

ACK(Message acknowledgment)默认是true
autoACK=true时,消息分发给消费者,则消息就会从内存中删除。如果正在执行的消费者宕机,则会丢失正在处理的消息。
所以autoACK=false时,则需要等待消息应答后才删除,如果消费者宕机,则会交付给其他消费者。

如果rabbitMQ宕机,则内存中的消息全部丢失。所以需要将消息持久化。(已经声明好的队列不能更改)

注意:RabbitMQ不允许重新定义一个已经存在的队列。控制台删除或者重新定义一个队列。
这里写图片描述
durable:持久化,本来声明在内存,持久化会保存到本地,重启mq不会消失
Exclusive:排外,如果是,两个消费者不能同时消费,一般就只有一个消费者
autoDelete:自动删除,最后一个消费者断开的时候自动删除队列

3、订阅者模式
这里写图片描述
一个生产者,多个消费者,消费者都有自己的队列,消息先发送到交换机exchange,每个队列都绑定到交换机。实现一个消息被多个消费者消费。
队列如果不绑定到交换机,消息丢失,交换机没有存储能力。
交换机:一方面是接收生产者的消息,另一方面是向队列推送消息。生产者在发布的时候不指定交换机,则为匿名发送。交换机类型如下
Fanout(不处理路由键),队列绑定到交换机,直接转发到所有队列。
Direct(处理路由键)
Topic()

这里写图片描述
消费者1和2分设定两个队列名称,绑定到交换机上,可以实现一个消息两个消费者订阅。
这里写图片描述

4、路由模式
声明交换机为direct,发送路由key为error的消息。
根据绑定的路由key,消息带哪个key,就路由到哪个队列。可以一个队列绑定多个key
这里写图片描述
这里写图片描述

声明交换机为topic 可以实现模式匹配
#匹配一个或多个 *匹配一个
这里写图片描述
这里写图片描述
这里写图片描述

四、消息确认机制 事务+confirm

可以通过持久化数据解决rabbitMQ服务器异常的数据丢失问题。但此时生产者并不知道消息是否发到rabbitMQ服务器中。如果生产者要确认消息已发送到MQ,可以通过两种方式。
1、通过AMQP协议方式,实现事务机制
txSelect—txCommit提交事务 txRollback回滚事务
用户将当前channel设置成transation模式 此时会导致大量的请求,极大的降低了吞吐量
这里写图片描述
2、生产者端引入confirm模式
队列如果已声明为tx不能重新设置为confirm
实现原理
这里写图片描述
好处:异步的处理
channel.setConfirmSelect()
编程模式
1、普通,发一条会调用waitForConfirm()
2、批量,每发送一批消息后再调用
3、异步的confirm模式,提供回调
单条或者批量(串行)发送confirm的生产者如下:
这里写图片描述
异步的confirm 集合存每一个未confirm的消息,confirm了,就从中删除
这里写图片描述

public class Send {
    private static  final  String QUEUE_NAME = "test_queue_confirm2";
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        //开启confirm模式
        channel.confirmSelect();

        //未确认的消息放入
        SortedSet<Long> confirmSet = Collections.synchronizedSortedSet(new TreeSet<Long>());

        //添加监听通道
        channel.addConfirmListener(new ConfirmListener() {
            //没有问题的handleAck 成功
            @Override
            public void handleAck(long deliveryTag, boolean multiple) throws IOException {
                if(multiple){   //多个的
                    System.out.println("handleAck:multiple");
                    confirmSet.headSet(deliveryTag+1).clear();
                }else{          //单个的
                    System.out.println("handleAck:multiple false");
                    confirmSet.remove(deliveryTag);
                }
            }
            //有问题的反馈Nack 失败
            @Override
            public void handleNack(long deliveryTag, boolean multiple) throws IOException {
                if(multiple){
                    System.out.println("handleNack:multiple");
                    confirmSet.headSet(deliveryTag+1).clear();
                }else{
                    System.out.println("handleNack:multiple false");
                    confirmSet.remove(deliveryTag);
                }
            }
        });

        String msg = "hello Confirm11111111";
        while(true){
            long seqNo = channel.getNextPublishSeqNo();
            channel.basicPublish("",QUEUE_NAME,null,msg.getBytes());
            confirmSet.add(seqNo);
        }
    }
}

五、SpringBoot集成RabbitMQ

在application.yml做mq配置
这里写图片描述
声明队列,交换机,路由键
这里写图片描述
生产者
这里写图片描述
消费者

这里写图片描述

  • 17
    点赞
  • 114
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值