rabbitmq在docker中启动即高级特性

systemctl start docker

docker ps -a

docker restart c086e473e4f9

1、SpringBoot整合RabbitMQ

  1、所需要的依赖

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

 2、生产者发送步骤

  2-1:配置application.yml

spring:
  rabbitmq:
    host: 192.168.153.130
    port: 5672
    username: itcast2
    password: itcast2
    virtual-host: "/itcast"  //mq的虚拟机 可以自己创建

2-2:配置mq的交换机和队列

package com.itheima.rabbitMq.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * @author shkstart
 * @create 2023-02-27 10:57
 */
@Configuration
public class RabbitMqConfig {

    public static final String EXCHANGE_TOPIC_NAME = "TOPIC_boot";
    public static final String QUEUE_TOPIC_NAME1 = "QUEUE_boot1";

    //配置交换机
    @Bean("bootExchange")
    public Exchange bootExchange(){
        return ExchangeBuilder.topicExchange(EXCHANGE_TOPIC_NAME).
                durable(true).build();
    }
    //配置队列
    @Bean("bootQueue")
    public Queue bootQueue(){
        return QueueBuilder.durable(QUEUE_TOPIC_NAME1).build();
    }

    //队列和交换机绑定
    /*
    1、知道队列是谁
    2、知道那个交换机
    3、routing key
     */
    @Bean("bingQueueExchange")
    public Binding bingQueueExchange(@Autowired Exchange bootExchange,
                                     @Autowired Queue bootQueue){
        return BindingBuilder.bind(bootQueue).
                to(bootExchange).
                with("boot.#").noargs();
    }


}

2-3:生产者发送消息

@SpringBootTest
@RunWith(SpringRunner.class)
public class ProducerTest {

    @Resource
    public RabbitTemplate rabbitTemplateL;

    @Test
    public void testPro(){
        String body = "宠他喵的我真尼玛服了";
        rabbitTemplateL.convertAndSend(RabbitMqConfig.EXCHANGE_TOPIC_NAME,"boot.xixi",body);
    }

}

 3、消费者接收消息

3-1:配置application.yml

spring:
  rabbitmq:
    host: 192.168.153.130
    port: 5672
    username: itcast2
    password: itcast2
    virtual-host: "/itcast"

 3-2:消费者接收消费信息

@Component
public class ConsumerTest {

    @RabbitListener(queues = RabbitMqConfig.QUEUE_TOPIC_NAME1)
    public void listenQueue(Message message){
        System.out.println(message);
    }

}

 2、mq的高级特性

 3:消息的可靠性

 2-2:配置yml文件,开启 publisher-confirms和publisher-returns

spring:
  rabbitmq:
    host: 192.168.153.130
    port: 5672
    username: itcast2
    password: itcast2
    virtual-host: "/itcast"
    publisher-confirms: true
    publisher-returns: true

2-3:开启交换机接收信息的确认模式

如果消息到了交换机,那么会执行setConfirmCallback的这个回调方法

    @Test
    public void testconfirm(){
        rabbitTemplateL.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean b, String s) {
                System.out.println("confirm方法被执行了");
            }
        });
        //发送消息
        rabbitTemplateL.convertAndSend(RabbitMqConfig.EXCHANGE_TOPIC_NAME,"aaa.boot.wokao","java退腿腿");
    }

2-4:开启队列接收信息的确认模式

当消息没到队列,那么就执行setReturnCallback的方法,进行下一步的处理

 /*
    回退模式
    当消息发送给exchange时,exchange会路由到queue,会自动确认消息,如果消息没有被确认,就会执行ReturnCallBack
    步骤:
    1、开启回退模式
    2、设置回调ReturnCallBack
    3、设置exchange处理消息的模式
        1、如果消息没有路由到queue,则丢弃消息
        2、如果消息没有路由到了queue,则返回给消息发送方ReturnCallBack
 */
    @Test
    public void testReturn(){
        //设置交换机处理失败消息的模式
        rabbitTemplateL.setMandatory(true);
        //设置会回调returnCallBack

        rabbitTemplateL.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            /**
             *
             * @param message 消息对象
             * @param replyCode 错误码
             * @param replyText 错误信息
             * @param exchange 交换机
             * @param routingKey 路由键
             */
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
                System.out.println("routingKey=" + routingKey);
                System.out.println("exchange=" + exchange);
                System.out.println("message" + message);
                System.out.println("消息没到队列");
            }
        });
        //发送消息
        rabbitTemplateL.convertAndSend(RabbitMqConfig.EXCHANGE_TOPIC_NAME,"aa.boot.wokao","java退腿腿我真真的哭死123");
    }

4 Consumer Ack

 4-1:设置消费者中的yml文件

spring:
  rabbitmq:
    host: 192.168.153.130
    port: 5672
    username: itcast2
    password: itcast2
    virtual-host: "/itcast"
#    publisher-confirms: true
#    publisher-returns: true
    listener:
      simple:
        acknowledge-mode: manual
      direct:
        acknowledge-mode: manual
#        acknowledge-mode: manual

 4-2:消费者的代码如下

@Component
@RabbitListener(queues = RabbitMqConfig.QUEUE_TOPIC_NAME1)
public class AckListener implements ChannelAwareMessageListener {
    @RabbitHandler
    public void process(String hello, Channel channel, Message message) throws IOException {
        System.out.println("HelloReceiver收到  : " + hello +"收到时间"+new Date());
        try {
            //告诉服务器收到这条消息 已经被我消费了 可以在队列删掉 这样以后就不会再发了 否则消息服务器以为这条消息没处理掉 后续还会在发
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
            //int i = 3/0;
            System.out.println("receiver success");
        } catch (Exception e) {
            e.printStackTrace();
            //将失败的信息重新返回给队列
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), true,true);
            System.out.println("receiver fail");
        }

    }

5、消费端限流

5-1:前提

 

/**
 * Consumer限流机制
 * 1、确保ack机制为手动确认
 * 2、在yml文件中设置消费端从mq拉取的最大消费消息数量prefetch
 *
 */

5-2:消费端中的yml配置文件的设置

prefetch就是代表着每次消费端可以从mq里面拿到消息数量

spring:
  rabbitmq:
    host: 192.168.153.130
    port: 5672
    username: itcast2
    password: itcast2
    virtual-host: "/itcast"
    listener:
      simple:
        acknowledge-mode: manual
        prefetch: 1
      direct:
        acknowledge-mode: manual
        prefetch: 1

5-3:消费端消费消息代码

@Component
public class QosListener  {

    @RabbitListener(queues = RabbitMqConfig.QUEUE_TOPIC_NAME1)
    @RabbitHandler
    public void process(String hello, Channel channel, Message message) throws IOException, InterruptedException {
        //获取消息
        System.out.println(new String(message.getBody()));
        //处理业务逻辑
        Thread.sleep(1000);
        //签收
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);

    }

6、TTL

 6-1:第一种可以给队列设置过期时间

withArgument("x-message-ttl",10000)设置了队列的过期时间,到指定时间后,该队列的所有消息都会过期
    @Bean("ttlQueue1")
    public Queue ttlQueue1(){
        return QueueBuilder.durable(QUEUE_TOPIC_TTL).withArgument("x-message-ttl",10000).build();
    }

6-2:第二种可以给消息本身设置过期时间

 @Test
    public void testTTL(){
        /**
         *
         */
        MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setExpiration("10000");
                return message;
            }
        };

        //发送消息
            rabbitTemplateL.convertAndSend(RabbitMqConfig.TTL_EXCHANGE,
                    "order.wokao",
                    "订单消息",messagePostProcessor);

    }

7、死信队列

 

 

 

 8、延迟队列

 

8-1:设置生产者的yml

spring:
  rabbitmq:
    host: 192.168.153.130
    port: 5672
    username: itcast2
    password: itcast2
    virtual-host: "/itcast"
    publisher-confirms: true
    publisher-returns: true

 8-2:配置相关的正常队列与交换机以及死信的队列和交换机

package com.example.bootproducer.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author shkstart
 * @create 2023-02-27 18:34
 */
@Configuration
public class producerConf {
    //正常交换机
    public  static final String ORDER_EXCHANGE = "order_exchange";
    //正常队列
    public static final String ORDER_QUEUE = "order_queue";

    //死心交换机
    public static final String ORDER_EXCHANGE_DLX = "order_exchange_dlx";
    //死心队列
    public static final String ORDER_QUEUE_DLX = "order_queue_dlx";

    /**
     * 延迟队列
     * 1、创建正常的交换机(order_exchange)和正常的队列(order_queue)
     * 2、创建死信的交换机(order_exchange_dlx)和死信的队列(order_queue_dlx)
     * 3、将正常的队列与死信交换机绑定关系
     */
    //正常的队列(order_queue)
    @Bean("getOrderQueue")
    public Queue getOrderQueue() {
        return QueueBuilder.durable(ORDER_QUEUE)
                .withArgument("x-message-ttl",20000)
                .withArgument("x-dead-letter-exchange",ORDER_EXCHANGE_DLX)
                .withArgument("x-dead-letter-routing-key","orderdlx.error")
                .build();
    }
    //创建正常的交换机(order_exchange)
    @Bean("getOrderExchange")
    public Exchange getOrderExchange() {
        return ExchangeBuilder.topicExchange(ORDER_EXCHANGE).durable(true).build();
    }
    //绑定正常的队列(order_queue)和创建正常的交换机(order_exchange)
    @Bean
    public Binding getOrderQueueAndexchange(@Qualifier("getOrderQueue") Queue queue,@Qualifier("getOrderExchange") Exchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("order.#").noargs();
    }


    //死心的队列(order_queue_dlx)
    @Bean("getOrderQueueDlx")
    public Queue getOrderQueueDlx() {
        return QueueBuilder.durable(ORDER_QUEUE_DLX).build();
    }
    //创建死心的交换机(order_exchange_dlx)
    @Bean("getOrderExchangeDlx")
    public Exchange getOrderExchangeDlx() {
        return ExchangeBuilder.topicExchange(ORDER_EXCHANGE_DLX).durable(true).build();
    }
    //绑定死心的队列(order_queue_dlx)和创建死心的交换机(order_exchange_dlx)
    @Bean
    public Binding getOrderQueueAndexchangeDlx(@Qualifier("getOrderQueueDlx") Queue queue,@Qualifier("getOrderExchangeDlx") Exchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("orderdlx.#").noargs();
    }




}

8-3:生产者发送消息

    @Test
    void contextLoads() {
        rabbitTemplate.convertAndSend(producerConf.ORDER_EXCHANGE,"order.xixi","我是一条死心消息");
    }

8-4:消费者接收消息(这个消息是从死信队列过来的)

package com.example.bootconsumer.Consumers;

import com.example.bootproducer.config.producerConf;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;

/**
 * @author shkstart
 * @create 2023-02-27 19:11
 */
@Component
public class consumerTest1 {

    @Resource
    public RabbitTemplate rabbitTemplate;

    @RabbitListener(queues = producerConf.ORDER_QUEUE_DLX)
    @RabbitHandler
    public void process(String hello, Channel channel, Message message) throws IOException {
        try {
            System.out.println("hello=" + hello );
            System.out.println(new String(message.getBody()));
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
        } catch (Exception e) {
            //
            channel.basicNack(message.getMessageProperties().getDeliveryTag(),true,false);
        }
    }
}

9、rabbitmq应用问题

9-1:消息可靠性保障

 

 9-2:消息幂等性保障

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值