RabbitMQ学习笔记

文章目录

    • 一、主流消息中间件介绍
    • 二、RabbitMQ
      • AMPQ高级消息队列协议
    • 三、安装与使用
      • 使用
    • 四、消息生产与消费
    • 五、Exchange交换机
      • Direct Exchange
    • 六、Message
    • 七、如何保证消息100%的投递成功
      • 可靠性投递
    • 八、幂等性
      • 如何避免消息重复消费
    • 九、Confirm确认消息
    • 十、Return消息机制
    • 十一、消费端
      • 自定义监听
      • 消息限流
      • 消费端ACK与重回队列机制
      • 死信队列

一、主流消息中间件介绍

ActiveMQ
RabbitMQ学习笔记_第1张图片
kafka性能好
RabbitMQ学习笔记_第2张图片
RocketMQ性能高(双十一)
RabbitMQ学习笔记_第3张图片
RabbitMQ可靠性、稳定性好(金融)
RabbitMQ学习笔记_第4张图片
RabbitMQ学习笔记_第5张图片

二、RabbitMQ

介绍
RabbitMQ学习笔记_第6张图片
高性能原因
RabbitMQ学习笔记_第7张图片

AMPQ高级消息队列协议

一种规范
RabbitMQ学习笔记_第8张图片
RabbitMQ学习笔记_第9张图片

三、安装与使用

使用

RabbitMQ学习笔记_第10张图片
修改配置文件
vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.6.5/ebin/rabbit.app
RabbitMQ学习笔记_第11张图片

运行
RabbitMQ学习笔记_第12张图片
管控台
查看插件:
rabbitmq-plugins list
启动管理插件
rabbitmq-plugins enable rabbitmq_management
检查是否启动
lsof -i:5672
访问
http://ip:15672
注意放行15672端口。或者直接关闭防火墙,否则无法访问
放行
firewall-cmd --zone=public --add-port=15672/tcp --permanent
重启防火墙
firewall-cmd --reload
命令行

四、消息生产与消费

Connection Factory:获取连接工厂
Connection:一个连接
Channel:数据通信信道,可发送和接收消息
Queue:具体的消息存储队列
Producer& Consumer生产和消费者

注意放行,否则会连接不上
放行
firewall-cmd --zone=public --add-port=5672/tcp --permanent
重启防火墙
firewall-cmd --reload

测试:
Procuder

   public static void main(String[] args) throws IOException, TimeoutException {
        //创建一个Connection工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("192.168.75.130");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        //创建连接
        Connection connection = factory.newConnection();

        //创建一个channel
        Channel channel = connection.createChannel();

        //通过channel发送
        String mesg = "hello world";
        for (int i = 0; i < 6; i++) {
            channel.basicPublish("", "test001", null, mesg.getBytes());
        }

        channel.close();
        connection.close();
    }

对于channel.basicPublish("", “test001”, null, mesg.getBytes());在这里插入图片描述
RabbitMQ学习笔记_第13张图片

Consumer

public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        //创建一个Connection工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setPort(5672);
        factory.setHost("192.168.75.130");
        factory.setVirtualHost("/");

        //创建连接
        Connection connection = factory.newConnection();

        //创建一个channel
        Channel channel = connection.createChannel();

        //创建一个队列
        String queueName = "test001";
        channel.queueDeclare(queueName, true, false, true, null);

        //创建一个消费者
        QueueingConsumer consumer = new QueueingConsumer(channel);

        //对channel进行设置
        channel.basicConsume(queueName, true, consumer);

        while (true) {
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            String msg = new String(delivery.getBody());
            System.out.println(msg);
        }
    }

关于basicConsumer()
注意:BasicConsume将信道设置为接收模式,直到取消队列的订阅为止,在接收模式期间,RabbitMQ会不断地推送消息给消费者,当然推送消息的个数还是会收到basicQos()的限制。如果只是想从队列获取单条消息而不是订阅,建议用basicGet()拉模式 。 将BasicGet()放在一个循环中代替BasicConsum()是不可取的

五、Exchange交换机

RabbitMQ学习笔记_第14张图片

Direct Exchange

所有发送到 Direct Exchange的消息被转发到 RouteKey中指定的 Queue
注意: Direct模式可以使用 RabbitMQ自带的 Exchange: defaultExchange,所以不需要将 Exchange进行任何绑定。若需要指定自定义exchange则需要绑定( binding操作,消息传递时, Routekey必须完全匹配才会被队列接收,否则该消息会被抛弃。如图所示
RabbitMQ学习笔记_第15张图片
实例:
RabbitMQ学习笔记_第16张图片

六、Message

本质上就是一段数据,由 Properties和 Payload(Body)组成
在生产者中:
RabbitMQ学习笔记_第17张图片
各种属性含义
RabbitMQ学习笔记_第18张图片
RabbitMQ学习笔记_第19张图片
在消费者中:

RabbitMQ学习笔记_第20张图片

七、如何保证消息100%的投递成功

RabbitMQ学习笔记_第21张图片

可靠性投递

方式1
消息落库,对消息状态进行打标(需要存储数据库,不适合高并发),通过检查数据库消息的状态判断是否成功。发送时status=0,成时status被改为:1;重试3次后则变为2

RabbitMQ学习笔记_第22张图片
方式2
消息的延迟投递,做二次确认,回调检查(高效,真正很多互联网公司所使用的方式)
RabbitMQ学习笔记_第23张图片

八、幂等性

.一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。我们实际系统中有很多操作,是不管做多少次,都应该产生一样的效果或返回一样的结果。如:扣款只扣一次,发消息只发一次。

如何避免消息重复消费

消费端实现幂等性,就意味着,我们的消息永远不会消费多次,即使我们收到了多条一样的消息。
业界主流的幂等性操作:

  • 唯一ID+指纹码机制,利用数据库主键去重
    RabbitMQ学习笔记_第24张图片
  • 利用 Redis的原子性去实现(set 或者自增)
    RabbitMQ学习笔记_第25张图片

九、Confirm确认消息

RabbitMQ学习笔记_第26张图片
RabbitMQ学习笔记_第27张图片
实例:
produceRabbitMQ学习笔记_第28张图片
consumer和前面的没什么变化
RabbitMQ学习笔记_第29张图片

十、Return消息机制

RabbitMQ学习笔记_第30张图片
在这里插入图片描述
RabbitMQ学习笔记_第31张图片
实例:当routingkey匹配不到的时候
RabbitMQ学习笔记_第32张图片

十一、消费端

自定义监听

我们一般就是在代码中编写 While循环,进行 consumer. nextDelivery方法进行获取下一条消息,然后进行消费处理!
但是我们使用自定义的Consumer更加的方便,解耦性更加的强,也是在实际工作中最常用的使用方式!
只需要继承一个类然后实现方法就行。
RabbitMQ学习笔记_第33张图片
创建一个consumer类继承DefaultConsumer

public class MyConsumer extends DefaultConsumer {

    /**
     * Constructs a new instance and records its association to the passed-in channel.
     *
     * @param channel the channel to which this consumer is attached
     */
    public MyConsumer(Channel channel) {
        super(channel);
    }

    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        System.out.println("consumerTag" + consumerTag);
        System.out.println("envelope" + envelope);
        System.out.println("body" + new String(body));
    }
}

在consumer中使用
在这里插入图片描述

消息限流

RabbitMQ学习笔记_第34张图片
如何实现
RabbitMQ提供了一种qos(服务质量保证)功能,即在非自动确认消息的前提下,如果一定数目的消息(通过基于 consume或者 channel设置Qos的值)未被确认前,不进行消费新的消息。(不设置自动签收)

在消费端中设置
RabbitMQ学习笔记_第35张图片
RabbitMQ学习笔记_第36张图片
实例:
consumer端限制(注意自定签收一定要设置为false)
RabbitMQ学习笔记_第37张图片

在自定义consumer中设置,注意在构造器中设置channel
RabbitMQ学习笔记_第38张图片

消费端ACK与重回队列机制

消费端重回队列是为了对没有处理成功的消息,把消息重新会递给Broker
般我们在实际应用中,都会关闭重回队列,也就是设置为 False

消费端的手工ACK和NACK

  • 消费端进行消费的时候,如果由于业务异常我们可以进行日志的记录,然后进行补偿!
  • 如果由于服务器宕机等严重问题,那我们就需要手工进行ACK保障消费端消费成功
    RabbitMQ学习笔记_第39张图片

死信队列

RabbitMQ学习笔记_第40张图片
RabbitMQ学习笔记_第41张图片

消息变成死信有一下几种情况

  • 消息被拒绝( basic. reject,/ basicnack)并且 requeue= false
  • 消息TTL过期
  • 队列达到最大长度

死信设置
-首先需要设置死信队列的 exchange和 queue,然后进行绑定:
Exchange: dlx. exchange
Queue: dlx.queue 监听
Routing key:# 任何routingkey都能路由

  • 然后我们进行正常声明交换机、队列、绑定,只不过我们需要在队列加上一个参数即可: arguments,put(" X-dead-letter-exchange",dIx. exchange")

你可能感兴趣的:(消息队列)