RabbitMQ之基础(一)

引入RabbitMQ

依赖

<!--mq-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
    <version>2.2.2.RELEASE</version>
</dependency>

常用配置

application.yml

# rabbitmq配置
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.password=guest
spring.rabbitmq.username=guest
spring.rabbitmq.virtual-host=MyHost1	//自定义的,在RabbitMQ页面手动创建一个,不配置使用RabbitMQ默认的"/" host
##消息确认配置项(手动确认要配置)
#1.确认消息已发送到交换机(Exchange)
spring.rabbitmq.publisher-confirm-type=correlated
#2.确认消息已经发送到队列(Queue)
spring.rabbitmq.publisher-returns=true

虚拟主机

rabbitMQ默认的虚拟主机为: “/” 。可通过RabbitMQ管理界面创建自定义虚拟主机,也可以通过以下命令:

#创建虚拟主机
rabbitmqctl add vhost [vhost_name]
#删除虚拟主机
rabbitmqctl delete vhost [vhost_name]
#列出虚拟主机
rabbitmqctl list_vhosts

消息投递策略

重启RabbitMQ服务器后队列和交换机会消失(durable属性默认为false),可设置队列和交换机的durable属性为true来持久化。

常用的交换机类型

direct

消息就投递到对应路由键匹配的队列

fanout

投递消息给所有绑定在当前交换机上面的队列

topic:

*,如:topic.hello
只有是消息携带的路由键是topic.hello,才会分发到该队列。

#,如:topic.#
只要是消息携带的路由键是以topic.开头,都会分发到该队列

常用

手动确认用法,简单用法demo参考:mycourse,example1项目。

消息确认

   推送消息存在四种情况:
      ①消息推送到server,但是在server里找不到交换机
      ②消息推送到server,找到交换机了,但是没找到队列
      ③消息推送到sever,交换机和队列啥都没找到
      ④消息推送成功

消费者端

@Override
public void onMessage(Message message, Channel channel) throws Exception {
	  long deliveryTag = message.getMessageProperties().getDeliveryTag();
	  // todo:业务处理
	   
	   //业务处理结果成功
	  if (true) {  
	  // 消费确认
       //channel.basicAck(deliveryTag, false) 第二个参数,手动确认可以被批处理,当该参数为 true 时,则可以一次性确认 delivery_tag 小于等于传入值的所有消息
        // channel.basicReject(deliveryTag, true);//第二个参数,true会重新放回队列,所以需要自己根据业务逻辑判断什么时候使用拒绝
      	channel.basicAck(deliveryTag, false);
      } else {

//
//    channel.basicNack(deliveryTag, false, true);
//    第一个参数依然是当前消息到的数据的唯一id;
//    第二个参数是指是否针对多条消息;如果是true,也就是说一次性针对当前通道的消息的tagID小于当前这条消息的,都拒绝确认。
//    第三个参数是指是否重新入列,也就是指不确认的消息是否重新丢回到队列里面去。
     	 channel.basicNack(deliveryTag, false, false);
      }
}
自动确认

自动确认, 这也是默认的消息确认情况。 AcknowledgeMode.NONE

根据情况确认

AcknowledgeMode.AUTO:

手动确认

开启AcknowledgeMode.MANUAL。
container.setAcknowledgeMode(AcknowledgeMode.MANUAL); // RabbitMQ默认是自动确认,这里改为手动确认消息

basic.ack用于肯定确认
basic.nack用于否定确认(这是AMQP 0-9-1的RabbitMQ扩展)
basic.reject用于否定确认,但与basic.nack相比有一个限制:一次只能拒绝单条消息

消费者端以上的3个方法都表示消息已经被正确投递,但是basic.ack表示消息已经被正确处理。而basic.nack,basic.reject表示没有被正确处理

1. channel.basicReject(deliveryTag, true);  
	拒绝消费当前消息,如果第二参数传入true,就是将数据重新丢回队列里,那么下次还会消费这消息。设置false,就是告诉服务器,我已经知道这条
消息数据了,因为一些原因拒绝它,而且服务器也把这个消息丢掉就行。 下次不想再消费这条消息了。
    使用拒绝后重新入列这个确认模式要谨慎,因为一般都是出现异常的时候,catch异常再拒绝入列,选择是否重入列,如果使用不当会导致一些每次都
被你重入列的消息一直消费-入列-消费-入列这样循环,会导致消息积压。

2.channel.basicNack(deliveryTag, false, true);
	第一个参数依然是当前消息到的数据的唯一id;
	第二个参数是指是否针对多条消息;如果是true,也就是说一次性针对当前通道的消息的tagID小于当前这条消息的,都拒绝确认。
	第三个参数是指是否重新入列,也就是指不确认的消息是否重新丢回到队列里面去。

生成者端

rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
	  	@Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                if (ack) {
                    //如果confirm返回成功 则进行更新消息投递成功
                    String msgId = correlationData.getId();
                   // 更新msgId对应状态为deliver_success
                } else {
                    //失败则进行具体的后续操作:重试 等
                    LOG.warn("<--消息发送到Exchange失败-->" + correlationData + cause);
                }
            }
})

交换机或路由键不存在

指定的路由键不存在,或者交换机不存在,那么消息就会return。

rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
     @Override
     public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {

	   LOG.warn("<---消息从Exchange路由到Queue失败--->");
       LOG.warn("ReturnCallback:     "+"消息:"+message);
       LOG.warn("ReturnCallback:     "+"回应码:"+replyCode);
       LOG.warn("ReturnCallback:     "+"回应信息:"+replyText);
       LOG.warn("ReturnCallback:     "+"交换机:"+exchange);
       LOG.warn("ReturnCallback:     "+"路由键:"+routingKey);
    }
});

消费端限流

Qos在非自动确认消息的情况下,在一定数量的消息未被消费前,不进行消费新的消息。

// prefetchSize消息的限制大小,一般设置为0,在生产端限制
// prefetchCount 我们一次最多消费多少条消息,一般设置为1
// global,一般设置为false,在消费端进行限制
channel.basicQos(int prefetchSize, int prefetchCount, boolean global) 

// 使用
channel.basicQos(0, 1, false);
channel.basicConsume(queueName, false, new MyConsumer(channel));    

死信队列(DLX)

进入死信队列3种情况:

1、basic.reject/basic.nack 并且 requeue为false(不重回队列)
2、消息TTL过期
3、队列达到最大的长度
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值