Rabbitmq学习笔记

Rabbitmq

什么是中间件

中间件的概念听起来高大上,但其实我们平时都在使用,例如MySQL就可以看作是具备中间件特性的一种技术,中间件技术必须遵循一定的规范和协议,例如 TCP/IP、UDP协议等等,无规矩不成方圆,只有遵守一定的协议才能去处理事情。MySQL 就遵循了 TCP/IP 协议,在我们平常的开发中使用不同的编程语言比如 Java、Go、Python 等来操作 MySQL 的前提也是要遵循 TCP/IP协议,根据此协议实现了不通语言的连接模块来达到通信的目的。由此说使用中间件需要解决的第一个问题就是互通性,也就是相互间可以通信。我们后续学习到其他中间件可能会看到更多其他的协议,比如 AMQP、HTTP 协议等等,为什么呢?因为 TCP/IP 协议是底层的操作系统协议,它并不能满足我们业务场景中的所有需求,所以在其基础上构建一个自己请求信息来实现一个新的协议,比如 AMQP 协议就在信息头中增加消息内容tag标签、队列名、交换机名、连接定制信息等等。

消息中间件

1、应用场景

  1. 跨系统数据传递
  2. 高并发的流量削峰
  3. 数据的分发和异步处理
  4. 大数据分析与传递
  5. 分布式事务

2、消息分发策略的机制和对比

ActiveMQRabbitMQKafkaRocketMQ
发布订阅支持支持支持支持
轮询分发支持支持支持/
公平分发/支持支持/
重发支持支持/支持
消息拉取/支持支持支持

3、串行执行和并行执行

阻塞和非阻塞

Rabbitmq的下载和安装

1.安装

2.1、下载RabbitMQ

下载地址:https://www.rabbitmq.com/download.html
image-20210505195722340
选择对应的系统版本点击下载,下载后会得到.rpm文件
image-20210306171625359

2.2、下载Erlang

RabbitMQ是采用 Erlang语言开发的,所以系统环境必须提供 Erlang环境,需要是安装 Erlang

ErlangRabbitMQ版本对照:https://www.rabbitmq.com/which-erlang.html

image-20210306105403265

这里安装最新版本3.8.14的RabbitMQ,对应的Erlang版本推荐23.x,我们下载erlang-23.2.7-2.el7.x86_64.rpm

下载地址:https://packagecloud.io/rabbitmq/erlang/packages/el/7/erlang-23.2.7-2.el7.x86_64.rpm
image-20210306155749846
其中的el7表示Red Hat 7.x,即CentOS 7.x

点击右上角下载即可得到.rpm文件
image-20210306171649898

2.3、安装Erlang

首先将下载好的文件上传到服务器,创建一个文件夹用来存放文件

[root@zsr ~]# mkdir -p /usr/rabbitmq

12

再利用xftp工具将上述下载的两个.rpm文件上传到服务器的刚创建的文件夹中
image-20210306171754048
然后切换到/usr/rabbitmq目录,解压安装erlang

# 解压
rpm -Uvh erlang-23.2.7-2.el7.x86_64.rpm

# 安装
yum install -y erlang

123456

image-20210306172313930
安装完成后输入如下指令查看版本号

erl -v

12

image-20210306172327030

2.4、安装RabbitMQ

RabiitMQ安装过程中需要依赖socat插件,首先安装该插件

yum install -y socat

12

然后解压安装RabbitMQ的安装包

# 解压
rpm -Uvh rabbitmq-server-3.8.14-1.el7.noarch.rpm

# 安装
yum install -y rabbitmq-server

123456

2.5、启动RabbitMQ服务

# 启动rabbitmq
systemctl start rabbitmq-server

# 查看rabbitmq状态
   systemctl status rabbitmq-server

123456

显示active则表示服务安装并启动成功
image-20210306173012889
其他命令:

# 设置rabbitmq服务开机自启动
systemctl enable rabbitmq-server

# 关闭rabbitmq服务
systemctl stop rabbitmq-server

# 重启rabbitmq服务
systemctl restart rabbitmq-server

123456789

3、RabbitMQWeb管理界面及授权操作

3.1、安装启动RabbitMQWeb管理界面

默认情况下,rabbitmq没有安装web端的客户端软件,需要安装才可以生效

# 打开RabbitMQWeb管理界面插件
rabbitmq-plugins enable rabbitmq_management

123

image-20210306191329997
然后我们打开浏览器,访问服务器公网ip:15672(注意打开阿里云安全组以及防火墙的15672端口),就可以看到管理界面
image-20210306193911485

rabbitmq有一个默认的账号密码guest,但该情况仅限于本机localhost进行访问,所以需要添加一个远程登录的用户

3.2、添加远程用户

# 添加用户
rabbitmqctl add_user 用户名 密码

# 设置用户角色,分配操作权限
rabbitmqctl set_user_tags 用户名 角色

# 为用户添加资源权限(授予访问虚拟机根节点的所有权限)
rabbitmqctl set_permissions -p / 用户名 ".*" ".*" ".*"

123456789

角色有四种

  • administrator:可以登录控制台、查看所有信息、并对rabbitmq进行管理
  • monToring:监控者;登录控制台,查看所有信息
  • policymaker:策略制定者;登录控制台指定策略
  • managment:普通管理员;登录控制

这里创建用户zsr,密码123456,设置administrator角色,赋予所有权限
image-20210306195558911
创建完成后,访问服务器公网ip:15672进行登录,然后便可进入到后台
image-20210306200132821

使用rabbitmq

五种工作模式

代码实现

package com.zyl.rabbitmq.simple;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;
//生产者
public class Producer {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("8.130.94.244");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        connectionFactory.setVirtualHost("/");
        Connection connection=null;
        Channel channel=null;
        try {
            //创建连接
            connection=connectionFactory.newConnection("生产者");
            //获取连接通道
            channel=connection.createChannel();
            //队列名称
            String QueueName="queue2";
            //设置参数
            channel.queueDeclare(QueueName,true,false,false,null);
            //准备消息内容
            String msg="hello rabbitmq";
            //发送消息
            channel.basicPublish("",QueueName,null,msg.getBytes());

            System.out.println("发送消息成功");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭通道
            if (channel!=null&&channel.isOpen()){
                channel.close();
            }
            //关闭连接
            if (connection!=null&&connection.isOpen()){
                connection.close();
            }
        }
    }
}
package com.zyl.rabbitmq.simple;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;
//消费者
public class Comsumer {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("8.130.94.244");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        connectionFactory.setVirtualHost("/");
        Connection connection=null;
        Channel channel=null;
        try {
            //创建连接
            connection=connectionFactory.newConnection("生产者");
            //获取连接通道
            channel=connection.createChannel();
            //发送消息
            channel.basicConsume("queue2", true, new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    System.out.println("接收到的消息是" + new String(delivery.getBody(), "UTF-8"));
                }
            }, new CancelCallback() {
                @Override
                public void handle(String s) throws IOException {
                    System.out.println("接受失败");
                }
            });
            System.out.println("开始接受消息");
            System.in.read();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭通道
            if (channel!=null&&channel.isOpen()){
                channel.close();
            }
            //关闭连接
            if (connection!=null&&connection.isOpen()){
                connection.close();
            }
        }
    }
}

批量应答

如果开启批量应答对进入消息信道的消息:容易消息丢失

消息的手动应答

package org.example.three;

import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
import org.example.utils.RabbitMqUtil;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class worker01 {
    public static final String QUEUE_NAME="ack_queue";

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        Channel channel = RabbitMqUtil.getChannel();

        //声明
        DeliverCallback deliverCallback=new DeliverCallback() {
            @Override
            public void handle(String s, Delivery delivery) throws IOException {
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("接收到的信息是:"+new String(delivery.getBody()));
                //手动应答  false表示不会批量应答
                channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
            }
        };

        //取消消息时的回调
        CancelCallback cancelCallback= s->System.out.println("消息终断");;

        /**
         * 消费信息
         */

        //是否自动应答
        boolean autoAck=false;

        channel.basicConsume(QUEUE_NAME, autoAck,deliverCallback,cancelCallback);
    }
}

RabbitMQ 为什么需要信道?为什么不是TCP直接通信?

  1. TCP的创建和销毁,开销大,创建需要三次握手,销毁需要四次分手

  2. 如果不使用信道,那么引用程序就会使用TCP的方式连接到rabbitmq,高峰时每秒成千上万条连接会造成资源的巨大浪费(一条tcp消耗资源,成千上万的tcp会非常消耗资源),而且操作系统每秒处理TCP连接数量也是有限的,必定会造成性能瓶颈

    3.信道的原理是一条线程一条信道,多条线程多条信道共同使用一条TCP连接。一条TCP连接可以容纳无限的信道,及时每秒造成成千上万的请求也不会造成性能瓶颈

消息持久化和消息持久化

1.设置队列持久化

2.设置消息持久化

3.发布确认

做到上面三步才能保证消息不丢失

//发布确认
channel.confirmSelect();

确认发布的策略

    public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {
        // 单个确认  168ms
        ConFirmMsg.ByOne();
        // 批量确认  28ms
        //ConFirmMsg.ByBatch();
        // 异步批量确认  22ms
        //ConFirmMsg.ByAsync();
    }

	//来一个信息确认一次
    public static void ByOne() throws IOException, TimeoutException, InterruptedException {
        Channel channel = RabbitMqUtil.getChannel();
        String queueName = UUID.randomUUID().toString();
        channel.confirmSelect();

        channel.queueDeclare(queueName, false, false, false, null);
        long begin = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            String s = i + "";
            channel.basicPublish("", queueName, null, s.getBytes());
            boolean result = channel.waitForConfirms();
            if (result) {
                System.out.println("发送成功");
            }
        }
        long end = System.currentTimeMillis();
        System.out.println(end - begin + "ms");
    }

    public static void ByBatch() throws IOException, TimeoutException, InterruptedException {
        Channel channel = RabbitMqUtil.getChannel();
        String queueName = UUID.randomUUID().toString();
        channel.confirmSelect();

        channel.queueDeclare(queueName, false, false, false, null);
        long begin = System.currentTimeMillis();

        int test = 100;
        for (int i = 0; i < 1000; i++) {
            String s = i + "";
            channel.basicPublish("", queueName, null, s.getBytes());
            if (i % test == 0) {
                boolean result = channel.waitForConfirms();
                if (result) {
                    System.out.println("发送成功");
                }
            }
        }
        long end = System.currentTimeMillis();
        System.out.println(end - begin + "ms");
    }

    public static void ByAsync() throws IOException, TimeoutException, InterruptedException {
        Channel channel = RabbitMqUtil.getChannel();
        String queueName = UUID.randomUUID().toString();
        channel.confirmSelect();

        channel.queueDeclare(queueName, false, false, false, null);

        //添加监听器
        channel.addConfirmListener(new ConfirmCallback() {
            @Override
            public void handle(long l, boolean b) throws IOException {
                System.out.println("消息发送成功");
            }
        }, new ConfirmCallback() {
            @Override
            public void handle(long l, boolean b) throws IOException {
                System.out.println("消息发送失败" + l);
            }
        });
        long begin = System.currentTimeMillis();

        for (int i = 0; i < 1000; i++) {
            String s = i + "";
            channel.basicPublish("", queueName, null, s.getBytes());
        }
        long end = System.currentTimeMillis();
        System.out.println(end - begin + "ms");
    }

不公平分发

    public static final String QUEUE_NAME="ack_queue";

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        Channel channel = RabbitMqUtil.getChannel();

        //声明
        DeliverCallback deliverCallback=new DeliverCallback() {
            @Override
            public void handle(String s, Delivery delivery) throws IOException {
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("接收到的信息是:"+new String(delivery.getBody()));
                //手动应答  false表示不会批量应答
                channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
            }
        };

        //取消消息时的回调
        CancelCallback cancelCallback= s->System.out.println("消息终断");;

        /**
         * 消费信息
         */

        //设置不公平分发
        int perfetCount=1;
        channel.basicQos(1);

        //是否自动应答
        boolean autoAck=false;

        channel.basicConsume(QUEUE_NAME, autoAck,deliverCallback,cancelCallback);
    }

消息的分发都是通过交换机

  1. 不设置会有默认交换机
  2. 然后通过队列存储

Fanout交换机

配置类

package com.zyl.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class rabbitmq {
    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("fanout_order_exchange",true,false);
    }
    @Bean
    public Queue smsQueue(){
        return new Queue("sms_fanout_queue",true);
    }
    @Bean
    public Queue msgQueue(){
        return new Queue("msg_fanout_queue",true);
    }
    @Bean
    public Queue emailQueue(){
        return new Queue("email_fanout_queue",true);
    }
    @Bean
    public Binding smsQueuebinding(){
        return BindingBuilder.bind(smsQueue()).to(fanoutExchange());
    }
    @Bean
    public Binding msgQueuebinding(){
        return BindingBuilder.bind(msgQueue()).to(fanoutExchange());
    }
    @Bean
    public Binding emailQueuebinding(){
        return BindingBuilder.bind(emailQueue()).to(fanoutExchange());
    }
}

具体实现

package com.zyl.service;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.UUID;

@Service
public class orderService {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    public void makeOrder(String userid,String goodid,int num){
        String orderid = UUID.randomUUID().toString();
        System.out.println("订单生成成功"+orderid);
        String ExchangeName="fanout_order_exchange";
        String routerKey="";
        rabbitTemplate.convertAndSend(ExchangeName,routerKey,orderid);
    }
}

Fanout消费者代码

package com.zyl.service.fanout;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
@RabbitListener(queues = {"email_fanout_queue"})
public class emailConsumer {
    @RabbitHandler
    public void reciveMessage(String msg){
        System.out.println("email接受到消息----"+msg);
    }
}

Direct交换机

生产者代码

package com.zyl.config;

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

@Configuration
public class directConfig {
    @Bean
    public DirectExchange directExchange(){
        return new DirectExchange("direct_order_exchange",true,false);
    }
    @Bean
    public Queue DirectsmsQueue(){
        return new Queue("sms_direct_queue",true);
    }
    @Bean
    public Queue DirectmsgQueue(){
        return new Queue("msg_direct_queue",true);
    }
    @Bean
    public Queue DirectemailQueue(){
        return new Queue("email_direct_queue",true);
    }
    @Bean
    public Binding DirectsmsQueuebinding(){
        return BindingBuilder.bind(DirectsmsQueue()).to(directExchange()).with("sms");
    }
    @Bean
    public Binding DirectmsgQueuebinding(){
        return BindingBuilder.bind(DirectmsgQueue()).to(directExchange()).with("msg");
    }
    @Bean
    public Binding DirectemailQueuebinding(){
        return BindingBuilder.bind(DirectemailQueue()).to(directExchange()).with("email");
    }
}

消费者代码

package com.zyl.service.direct;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
@RabbitListener(queues = {"email_direct_queue"})
public class DirectemailConsumer {
    @RabbitHandler
    public void DirectreciveMessage(String msg){
        System.out.println("email接受到消息----"+msg);
    }
}

Topic交换机模式(使用注解开发)

消费者代码

package com.zyl.service.topic;

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;

@Component
@RabbitListener(bindings = @QueueBinding(
        value = @Queue(value = "email.topic.queue",durable = "true",autoDelete = "false"),
        exchange = @Exchange(value = "topic_order_exchange",type = ExchangeTypes.TOPIC),
        key = "com.#"
))
public class TopicemailConsumer {
    @RabbitHandler
    public void reciveMessage(String msg){
        System.out.println("email接受到消息----"+msg);
    }
}

设置过期时间

package com.zyl.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;

@Configuration
public class ttl {
    @Bean
    public DirectExchange ttlExchange(){
        return new DirectExchange("ttl_exchange",true,false);
    }
    @Bean
    public Queue ttlQueue(){
        //设置过期时间
        HashMap<String, Object> map = new HashMap<>();
        map.put("x-message-ttl",5000);
        return new Queue("ttl_direct_queue",true,false,false,map);
    }
    @Bean
    public Binding TtlQueuebinding(){
        return BindingBuilder.bind(ttlQueue()).to(ttlExchange()).with("as");
    }
}

死信队列

1.就是处理设置了过期的队列信息

2.队列的长度达到了最大值

3.没有被消费的消息

代码演示

1.设置过期时间

 //生产者
 public static final String NORMAL_EXCHANGE="normal_exchange";
    public static void main(String[] args) throws IOException, TimeoutException {
        Channel channel = RabbitMqUtil.getChannel();

        AMQP.BasicProperties properties=new AMQP.BasicProperties()
                .builder()
                .expiration("10000")
                .build();

        for (int i = 1; i < 11; i++) {
            String msg=i+"";
            channel.basicPublish(NORMAL_EXCHANGE,"zhangsan",properties,msg.getBytes());
        }
    }
   //普通消费者
   public static final String NORMAL_EXCHANGE="normal_exchange";
    public static final String DEAD_EXCHANGE="dead_exchange";
    public static final String NORMAL_QUEUE="normal_queue";
    public static final String DEAD_QUEUE="dead_queue";

    public static void main(String[] args) throws IOException, TimeoutException {
        Channel channel = RabbitMqUtil.getChannel();

        channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
        channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);

        HashMap<String, Object> map = new HashMap<>();
        // 设置过期时间
        //设置发送到死信交换机
        map.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        //设置路由key
        map.put("x-dead-letter-routing-key","lisi");


        //普通队列的声明
        channel.queueDeclare(NORMAL_QUEUE,false,false,false,map);
        channel.queueDeclare(DEAD_QUEUE,false,false,false,null);

        //绑定交换机
        channel.queueBind(NORMAL_QUEUE,NORMAL_EXCHANGE,"zhangsan");
        channel.queueBind(DEAD_QUEUE,DEAD_EXCHANGE,"lisi");

        System.out.println("C1等待消费.....");

        DeliverCallback deliverCallback = new DeliverCallback() {
            @Override
            public void handle(String s, Delivery delivery) throws IOException {
                System.out.println("c1----->"+new String(delivery.getBody()));
            }
        };

        channel.basicConsume(NORMAL_QUEUE, true, deliverCallback, s->{});
    }

2.队列达到最大长度

    public static final String NORMAL_EXCHANGE="normal_exchange";
    public static final String DEAD_EXCHANGE="dead_exchange";
    public static final String NORMAL_QUEUE="normal_queue";
    public static final String DEAD_QUEUE="dead_queue";

    public static void main(String[] args) throws IOException, TimeoutException {
        Channel channel = RabbitMqUtil.getChannel();

        channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
        channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);

        HashMap<String, Object> map = new HashMap<>();
        // 设置过期时间
        //设置发送到死信交换机
        map.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        //设置路由key
        map.put("x-dead-letter-routing-key","lisi");
        //设置队列的长度
        map.put("x-max-length",6);

        //普通队列的声明
        channel.queueDeclare(NORMAL_QUEUE,false,false,false,map);
        channel.queueDeclare(DEAD_QUEUE,false,false,false,null);

        //绑定交换机
        channel.queueBind(NORMAL_QUEUE,NORMAL_EXCHANGE,"zhangsan");
        channel.queueBind(DEAD_QUEUE,DEAD_EXCHANGE,"lisi");

        System.out.println("C1等待消费.....");

        DeliverCallback deliverCallback = new DeliverCallback() {
            @Override
            public void handle(String s, Delivery delivery) throws IOException {
                System.out.println("c1----->"+new String(delivery.getBody()));
            }
        };

        channel.basicConsume(NORMAL_QUEUE, true, deliverCallback, s->{});
    }

3.消息被拒绝

    public static final String NORMAL_EXCHANGE="normal_exchange";
    public static final String DEAD_EXCHANGE="dead_exchange";
    public static final String NORMAL_QUEUE="normal_queue";
    public static final String DEAD_QUEUE="dead_queue";

    public static void main(String[] args) throws IOException, TimeoutException {
        Channel channel = RabbitMqUtil.getChannel();

        channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
        channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);

        HashMap<String, Object> map = new HashMap<>();
        // 设置过期时间
        //设置发送到死信交换机
        map.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        //设置路由key
        map.put("x-dead-letter-routing-key","lisi");

        //普通队列的声明
        channel.queueDeclare(NORMAL_QUEUE,false,false,false,map);
        channel.queueDeclare(DEAD_QUEUE,false,false,false,null);

        //绑定交换机
        channel.queueBind(NORMAL_QUEUE,NORMAL_EXCHANGE,"zhangsan");
        channel.queueBind(DEAD_QUEUE,DEAD_EXCHANGE,"lisi");

        System.out.println("C1等待消费.....");

        DeliverCallback deliverCallback = new DeliverCallback() {
            @Override
            public void handle(String s, Delivery delivery) throws IOException {
                String msg = new String(delivery.getBody());
                if (msg.equals("5")){
                    System.out.println(msg+"----被拒收");
                    channel.basicReject(delivery.getEnvelope().getDeliveryTag(),false);
                }else {
                    System.out.println("c1----->"+msg);
                    channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
                }
            }
        };

        //关闭自动应答
        channel.basicConsume(NORMAL_QUEUE, false, deliverCallback, s->{});
    }

SpringBoot整合rabbitmq

1.导入坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2.写配置文件

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

3.代码实现(定义)

    public static final String X_EXCHANGE="X";
    public static final String DEAD_EXCHANGE="Y";
    public static final String QUEUE_A="A";
    public static final String QUEUE_B="B";
    public static final String DEAD_QUEUE="C";
    //普通交换机
    @Bean
    public DirectExchange X(){
        return new DirectExchange(X_EXCHANGE);
    }
    //死信交换机
    @Bean
    public DirectExchange Y(){
        return new DirectExchange(DEAD_EXCHANGE);
    }
    //延迟队列1
    @Bean
    public Queue queueA(){
        HashMap<String, Object> map = new HashMap<>();
        //设置死信交换机
        map.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        //设置死信路由key
        map.put("x-dead-letter-routing-key","YD");
        //设置TTL
        map.put("x-message-ttl",10000);
        return QueueBuilder.durable(QUEUE_A).withArguments(map).build();
    }
    //延迟队列2
    @Bean
    public Queue queueB(){
        HashMap<String, Object> map = new HashMap<>();
        //设置死信交换机
        map.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        //设置死信路由key
        map.put("x-dead-letter-routing-key","YD");
        //设置TTL
        map.put("x-message-ttl",40000);
        return QueueBuilder.durable(QUEUE_B).withArguments(map).build();
    }
    //死信队列
    @Bean
    public Queue queueC(){
        return QueueBuilder.durable(DEAD_QUEUE).build();
    }
    //队列绑定
    @Bean
    public Binding xBindA(){
        return BindingBuilder.bind(queueA()).to(X()).with("XA");
    }
    @Bean
    public Binding xBindB(){
        return BindingBuilder.bind(queueB()).to(X()).with("XB");
    }
    @Bean
    public Binding yBindC(){
        return BindingBuilder.bind(queueC()).to(Y()).with("YD");
    }

3.消费者

@Component
public class DeadConsumer {
    @RabbitListener(queues = "C")
    public void receive(Message message, Channel channel){
        System.out.println(new String(message.getBody()));
    }
}

4.生产者

@RestController
public class send {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @GetMapping("/ttl")
    public void sendMsg(){
        System.out.println(LocalDateTime.now().toString());
        rabbitTemplate.convertAndSend("X","XA", LocalDateTime.now().toString());
        rabbitTemplate.convertAndSend("X","XB", LocalDateTime.now().toString());
    }
}

延迟队列(定义)

    public static final String X_EXCHANGE="X";
    public static final String DEAD_EXCHANGE="Y";
    public static final String QUEUE_A="A";
    public static final String QUEUE_B="B";
    public static final String DEAD_QUEUE="C";
    //普通交换机
    @Bean
    public DirectExchange X(){
        return new DirectExchange(X_EXCHANGE);
    }
    //死信交换机
    @Bean
    public DirectExchange Y(){
        return new DirectExchange(DEAD_EXCHANGE);
    }
    //延迟队列1
    @Bean
    public Queue queueA(){
        HashMap<String, Object> map = new HashMap<>();
        //设置死信交换机
        map.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        //设置死信路由key
        map.put("x-dead-letter-routing-key","YD");
        //设置TTL
        map.put("x-message-ttl",10000);
        return QueueBuilder.durable(QUEUE_A).withArguments(map).build();
    }
    //延迟队列2
    @Bean
    public Queue queueB(){
        HashMap<String, Object> map = new HashMap<>();
        //设置死信交换机
        map.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        //设置死信路由key
        map.put("x-dead-letter-routing-key","YD");
        //设置TTL
        map.put("x-message-ttl",40000);
        return QueueBuilder.durable(QUEUE_B).withArguments(map).build();
    }
    //死信队列
    @Bean
    public Queue queueC(){
        return QueueBuilder.durable(DEAD_QUEUE).build();
    }
    //队列绑定
    @Bean
    public Binding xBindA(){
        return BindingBuilder.bind(queueA()).to(X()).with("XA");
    }
    @Bean
    public Binding xBindB(){
        return BindingBuilder.bind(queueB()).to(X()).with("XB");
    }
    @Bean
    public Binding yBindC(){
        return BindingBuilder.bind(queueC()).to(Y()).with("YD");
    }

1.消费者

    @RabbitListener(queues = "C")
    public void receive(Message message, Channel channel){
        System.out.println(new String(message.getBody()));
    }

2.生产者

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @GetMapping("/ttl")
    public void sendMsg(){
        System.out.println(LocalDateTime.now().toString());
        rabbitTemplate.convertAndSend("X","XA", "第一条消息");
        rabbitTemplate.convertAndSend("X","XB", "第二条消息");
    }
 map.put("x-message-ttl",40000);
    return QueueBuilder.durable(QUEUE_B).withArguments(map).build();
}
//死信队列
@Bean
public Queue queueC(){
    return QueueBuilder.durable(DEAD_QUEUE).build();
}
//队列绑定
@Bean
public Binding xBindA(){
    return BindingBuilder.bind(queueA()).to(X()).with("XA");
}
@Bean
public Binding xBindB(){
    return BindingBuilder.bind(queueB()).to(X()).with("XB");
}
@Bean
public Binding yBindC(){
    return BindingBuilder.bind(queueC()).to(Y()).with("YD");
}

## 1.消费者

@RabbitListener(queues = "C")
public void receive(Message message, Channel channel){
    System.out.println(new String(message.getBody()));
}

## 2.生产者

@Autowired
private RabbitTemplate rabbitTemplate;
@GetMapping("/ttl")
public void sendMsg(){
    System.out.println(LocalDateTime.now().toString());
    rabbitTemplate.convertAndSend("X","XA", "第一条消息");
    rabbitTemplate.convertAndSend("X","XB", "第二条消息");
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值