RabbitMQ知识介绍

1.amqp协议介绍:

RabbitMQ是基于amqp协议的一种实现,学习rabbitmq需要先仔细学习amqp。
AMQP官网:http://www.amqp.org/product/architecture
其他一篇介绍很详细的博客:https://blog.csdn.net/weixin_37641832/article/details/83270778

2.rabbitmq核心概念:

2.1 Exchange:
2.2.1 exchange属性介绍:
属性名备注
name★ 交换机名
type★ 交换机类型:direct、topic、fanout、headers
durability★ 是否需要持久化,true为持久化
auto Delete★ 当最后一个绑定到该交换机的队列删除,是否本身也自动删除
internal该exchange是否为rabbitmq内部使用,默认为false。绝大多数情况用不着,类如要扩展rabbitmq插件时可能会使用到。
arguments扩展参数,用于扩展amqp协议定制化使用
2.2.2 交换机类型介绍:
交换机类型说明
direct直连交换机,所有生产者发送到direct exchange的消息,会被转发到与routingKey有完全匹配关系的queue。RabbitMQ有默认的直连交换机:Default Exchange,可以直接使用。
topictopic交换机,所有生产者发送到topic exchange的消息,都会被转发到所有关系routingKey指定topic的queue。exchange会将routingKey和某topic进行模糊匹配,队列需要绑定到某个topic。可以使用通配符进行模糊匹配,"#“匹配一个或多个词,”*"只能匹配一个词。
fanout不处理路由键,只需简单的将队列绑定到交换机上。生产者发送到交换机的消息,都会被转发到与该交换机有绑定的所有queue上。fanout交换机转发消息是最快的。
2.2.3 实现示例:
/**
 * 第一个参数:交换机名
 * 第二个参数:交换机类型(DIRECT,TOPIC,FANOUT,HEADERS)
 * 第三个参数:durable,是否持久化
 * 第四个参数:autoDelete,是否自动删除
 * 第五个参数:arguments,扩展参数
*/
channel.exchangeDeclare(exchangeName, BuiltinExchangeType.DIRECT, true, false, MessageProperties.PERSISTENT_TEXT_PLAIN);
2.3 queue:
2.3.1 queue属性介绍:
属性名备注
name★ 队列名
durability★ 是否需要持久化,trurable为持久化,transient为不持久化。
auto Delete★ 当最后一个监听被移除之后,是否本身自动删除
arguments扩展参数,用于扩展amqp协议定制化使用
2.3.2 实现示例:
/**
 * 第一个参数:队列名
 * 第二个参数:durable,是否持久化
 * 第三个参数:是否独占式获取消息
 * 第四个参数:autoDelete,是否自动删除
 * 第五个参数:arguments,扩展参数
*/
channel.queueDeclare(queueName, true, false, false, null);
2.4 binding:
2.4.1 概述:

指exchange和exchange、queue之间的绑定关系。

2.3.2 实现示例:
/**
 * 第一个参数:队列名
 * 第二个参数:交换机名
 * 第三个参数:路由键
*/
channel.queueBind(queueName, exchangeName, routingKey);
2.5 Message:
2.5.1 概述:

指服务器和应用程序之间传送的数据,由Properties和Payload(body)组成。

  • Properties中的属性:

content_type:传输协议
content_encoding:编码方式
priority:优先级
correlation_id:请求的唯一标识。
reply_to:rpc属性,
expiration:消息过期时间
message_id:消息的id
timestamp:消息的时间戳

  • Payload(body):

即发送的消息内容。

2.5.2 实现实例:
//自定义扩展headers属性
Map<String, Object> headers = new HashMap<>();
headers.put("attr1", "扩展的属性1");
headers.put("attr2", "扩展的属性2");
//拼装消息properties
AMQP.BasicProperties properties = new AMQP.BasicProperties().builder()
        .deliveryMode(2)            //持久化模式
        .contentEncoding("utf-8")   //编码
        .expiration("5000")         //过期时间
        .headers(headers)           //headers扩展属性
        .build();
//消息体Payload(Body)
String body = "hello rabbit!!! " + i;
//5.生产消息
channel.basicPublish(exchangeName, routingKey, properties, body.getBytes());

3.rabbitmq高级特性:

3.1 confirm监听机制:
3.1.1 概述:

确认监听机制:生产者投递消息后,如果broker收到消息,会给生产者发送一个应答。生产者根据应答,来确定消息是否正常发送到了broker。这是rabbitmq消息投递可靠性的核心保障!

3.1.2 流程图:

image

3.1.3 实现:

1.在channel上开启确认模式:channel.confirmSelect()
2.在channel上添加监听:addConfirmListener,监听成功或失败的返回结果,进行相应处理,如消息重发、做日志记录后续补偿等。

//6.指定消息投递模式:确认模式
channel.confirmSelect();
//7.设置confirm监听
channel.addConfirmListener(new ConfirmListener() {
    @Override
    public void handleAck(long l, boolean b) throws IOException {
        System.out.println("---------- 在此ack!!------------");
    }
    @Override
    public void handleNack(long l, boolean b) throws IOException {
        System.out.println("---------- 在此noack!!------------");
    }
});
3.2 return监听机制:
3.2.1 概述:

return监听机制:用于处理一些生产者发送消息到broker之后,根据exchange、routingKey不可路由到queue的消息。

3.2.2 流程图:

image

3.2.3 实现:

1.在channel上添加监听:addReturnListener,监听消息不可达时的通知。
2.在消息发送时,设置mandatory为true。

//4.设置return监听
channel.addReturnListener(new ReturnListener() {
    @Override
    public void handleReturn(int replyCode, String replyText, String exchange,
        String routingKey, AMQP.BasicProperties basicProperties, byte[] body) throws IOException {
        System.out.println("收到不可路由的消息:");
        System.out.println("replyCode: "+replyCode);
        System.out.println("replyText: "+replyText);
        System.out.println("exchange: "+exchange);
        System.out.println("routingKey: "+routingKey);
        System.out.println("basicProperties: "+basicProperties);
        System.out.println("body: "+new String(body));
    }
});
//7.生产消息
String msg = "hello rabbit!!! ";
// 注意这里的第三个参数:boolean mandatory 是否开启return通知。
// 当设置为true:该消息时不可路由的时,rabbitMQ会回调上面添加的returnListener方法;
// 当设置为false:该消息时不可路由的时,rabbitMQ会在broker端直接把该消息清除。
channel.basicPublish(exchangeName, routingKeyError, true, null, msg.getBytes());
3.3 ack机制:
3.3.1 概述:

消费端通过ack操作,来通知mq该消息是否正常接收到了。

3.3.2 实现:
public class MyConsumer extends DefaultConsumer {
    private Channel channel;
    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);
        System.out.println(envelope.toString());
        System.out.println(properties.toString());
        System.out.println("消息内容:" + new String(body));
        //手动ack
//        channel.basicAck(envelope.getDeliveryTag(), false);
        /**
         * 手动nack
         * 注意第三个参数:是否重回队列。
         *  如果设为true,该消息会被rabbitmq重新放到队列的尾端,等待下次推送;
         *  如果设为false,该消息不会重回队列,这时主要靠日志记录后续补偿处理。
         *  一般都会把重回队列关闭。
         */
        channel.basicNack(envelope.getDeliveryTag(), false, false);
    }
}
3.4 消费端限流:
3.4.1 为何需要消费端限流:

假设有个场景,MQ服务器发生消息积压,有成千上万条待处理的消息,这时打开一个消费者客户端,大量的消息推送过来,单个客户端处理不过来,导致服务崩溃。

3.4.2 概述:

RabbitMQ提供一种qos(服务质量保证)功能,即在【非自动确认消息的前提】下,如果一定数目的消息未被确认前,不进行消费新的消息。

3.4.3 实现:
/**
 * 消费端限流:
 * 第一个参数:prefetchSize,消费的单条消息大小限制,如果为0表示不限制。
 * 第二个参数:prefetchCount,告诉RabbitMQ不要一次给消费者推送多余N个消息,直到这N个消息已全部被ack了。
 * 第三个参数:global,true表示此设置应用于channel级别,false表示应用于consumer级别。
*/
channel.basicQos(0, 1, false);

//9.消费消息
// 一定注意此处,ack设置为手动ack,否则限流不生效
channel.basicConsume(queueName, false, consumer);
3.5 ttl:
3.5.1 概述:

Rabbitmq中可以给消息/队列设置存活时间,当该消息被转发到队列时开始计时,如果没有在该存活时间内被消费掉,消息会被自动清除。

3.5.2 实现:
//拼装消息properties
AMQP.BasicProperties properties = new AMQP.BasicProperties().builder()
        .deliveryMode(2)            //持久化模式
        .contentEncoding("utf-8")   //编码
        .expiration("5000")         //ttl过期时间
        .headers(headers)            //headers扩展属性
        .build();
//5.生产消息
channel.basicPublish(exchangeName, routingKey, properties, msg.getBytes());
3.6 死信队列:
3.6.1 概述:

死信队列:DLX,Dead-Letter-Exchange
利用死信队列,当消息在一个队列中变成死信(dead message)时,能被重新publish到另一个exchange中。

  • 消息变成死信有以下几种情况:

1.消息ttl(存活时间)过期
2.消息被拒绝(basic.nack/basic.reject),并没有没重回队列(requeue=false)
3.队列达到最大长度

  • 死信队列说明:

1.DLX也是个正常的exchange,和一般的exchange没有区别,只不过它被绑定到某个queue上,作为死信转发使用。
2.当与它绑定的queue中有死信产生时,rabbitmq会自动将该死信转发给该exchange,进而被路由到另一队列。
3.可以监听后面这个队列作相应处理。

3.6.2 实现:

1.设置一个死信队列:dlx.exchange
2.给正常使用的一个队列,加上arguments.put(“x-dead-letter-exchange”, “dlx.exchange”)
这样当该队列有死信消息时,就会被publish到dlx.exchange上。

//4.声明一个死信队列,该步骤跟声明一个正常队列一样。
channel.exchangeDeclare("dlx.exchange", BuiltinExchangeType.TOPIC, true, false, null);
channel.queueDeclare("dlx.queue", true, false, false, null);
channel.queueBind("dlx.queue", "dlx.exchange", "#");
//5.声明要正常使用的exchange、queue、binding
String exchangeName = "test_dead_exchange";
String queueName = "test_dead_queue";
String routingKey = "test.dead";
channel.exchangeDeclare(exchangeName, BuiltinExchangeType.DIRECT, false, false, null);
/**
 * 6.注意在此步骤:
 *  要给此正常使用的queue添加一个arguments,设置"x-dead-letter-exchange"为刚才声明的死信exchange名
 */
Map<String, Object> arguments = new HashMap<>();
arguments.put("x-dead-letter-exchange", "dlx.exchange");
channel.queueDeclare(queueName, false, false, false, arguments);
channel.queueBind(queueName, exchangeName, routingKey);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RabbitMQ是一种消息队列(MQ)系统,它具有多个相关概念和模式。其中一些重要的知识点包括: 1. RabbitMQ的四大概念:生产者、消费者、交换机和队列,它们一起构成了消息传递的基本组成部分。 2. RabbitMQ的六种模式:简单模式、工作模式、轮询分发、消息应答、自动应答和手动应答。 3. RabbitMQ持久化消息:可以将消息持久化到磁盘上,以防止消息在RabbitMQ发生故障时丢失。 4. 死信队列:当消息因某些原因无法被消费时,可以将其发送到死信队列中进行处理。 5. 延迟队列:可以设置消息的延迟时间,使其在一定时间后被消费。 6. 发布确认:可以通过发布确认机制来确保消息被成功发送到RabbitMQ。 7. RabbitMQ集群:可以通过搭建集群来实现高可用性和负载均衡。 8. 幂等性:消息的幂等性指的是多次处理同一消息不会产生副作用。 9. 优先级队列:可以为消息设置优先级,以确保高优先级的消息能够更快地被消费。 10. 惰性队列:惰性队列指的是只有在需要时才会被创建。 这些是RabbitMQ的一些重要知识点,它们可以帮助我们更好地理解和应用RabbitMQ。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [RabbitMQ 知识点总结](https://blog.csdn.net/PaperJack/article/details/124734987)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [RabbitMQ知识点](https://blog.csdn.net/weixin_42100694/article/details/113514641)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值