2021-10-02

win10系统中配置rabbitmq

安装包提取码:
链接:https://pan.baidu.com/s/1zkSkM0VSphUzfbYCbjVAfg
提取码:0kmv

具体配置如下:
安装一路默认即可

1、安装erlang环境

在电脑环境变量中添加新的变量名
ERLANG_HOME=E:\Program Files\erl9.0
再path中添加
%ERLANG_HOME%\bin;%RABBITMQ_SERVER%\sbin

2、安装rabbitMq

 在  E:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.10\sbin>  下运行 rabbitmq-plugins enable rabbitmq_management

 浏览器运行:
 http://localhost:15672/#/
 用户名; guest  密码; guest

3、rabbitmq工作原理
在这里插入图片描述组成部分说明:
producer 生产者: 生产者负责发送消息
channel 连接管道: 负责建立消费者或生产者的tcp长连接
Broker 服务器: 消息队列服务进程 此服务包括两个部分 exchange queue
Exchange 交换机: 负责消息的匹配和转发
queue 队列消息: 存储消息的队列
congsumer 消费者:负责消费队列中的消息
生产者生产消息过程:
1、生产者和rabbitmq建立管道连接
2、生产者指定对列或者交换机 路由或通配符等信息
3、生产者向管道中发送消息
4、关闭管道 和 rabbitmq连接
消费者消费消息过程
1、建立服务器tcp长连接
2、创建队列并设置队列的属性信息
3、绑定队列与交换机 通配符 路由key等信息
4、消费者获取消息
5、手动确认机制或者 自定ack确认机制

package common.projects.devlop.utils;

import com.rabbitmq.client.*;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.TimeoutException;


@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ProducerSendMsg {

    @ApiModelProperty(value = "rabbitmq连接客户端")
    private Connection connection;

    @ApiModelProperty(value = "消息对列")
    private String queue;

    @ApiModelProperty(value = "是否持久化存储消息")
    private Boolean durable;

    @ApiModelProperty(value = "是否独占连接")
    private Boolean exclusive;

    @ApiModelProperty(value = "是否自动删除")
    private Boolean autoDelete;

    @ApiModelProperty(value = "设置额为参数 如: 队列存活时间")
    private Map<String,Object> arguments;

    @ApiModelProperty(value = "队列消息")
    private String queueMsg;

    @ApiModelProperty(value = "rabbitmq交换机")
    private String exchange;

    @ApiModelProperty(value = "交换机类型")
    private BuiltinExchangeType exchangeType;

    @ApiModelProperty(value = "rabbitmq交换机路由key")
    private String routingKey;

    @ApiModelProperty(value = "消息的属性")
    private String props;


    public void sendMsg() throws IOException, TimeoutException, InterruptedException {
        // 1、创建连接管道 建立tcp长连接管道
        Channel channel = connection.createChannel();
        /**
         * 2、创建管道连接的消息队列
         * @param queue 队列
         * @param durable 是否持久化对列存储 如果设置为持久化存储 在重启rabbitmq以后该队列还会存在rabbitmq服务器中
         * @param exclusive 是否独占连接 该对列只能在本次连接中使用 如果连接关闭则该对列自动删除 如果设置为true可用于创建临时对列
         * @param autoDelete 是否自动删除 当对列为空的时候自动删除 配置exclusive使用可实现临时对列
         * @param arguments 额外参数配置 一般可用于设置 对列存活时间
         */
        channel.queueDeclare(queue,durable,exclusive,autoDelete,arguments); //队列名称 是否持久化对列 是否独占连接 是否自动删除 额外参数设置
        /**
         * rabbitmq生产者数据丢失问题解决方法
         * 1、声明开启mq事务 保证生产者数据的完性 由于事务开启和事务关闭的两个速度差为149倍 一般很少使用rabbitmq事务
         *        try {
         *           channel.txSelect(); // 1.1、声明开启一个事务
         *           channel.basicPublish(exchange,queue,routingKey,queueMsg.getBytes(StandardCharsets.UTF_8));
         *           channel.txCommit(); // 1.2、事务的提交
         *        }catch (Exception ex){
         *           channel.txRollback(); // 1.3、发生错误事务回滚
         *        }finally {
         *           // 3、关闭通道和客户端的连接
         *           channel.close();
         *           connection.close();
         *        }
         *  2、confirm发送方确认机制  confirm的三种确认机制
         *     2.1 channel.waitForConfirms() 普通confirm普通消息机制
         *     channel.confirmSelect(); //开启confirm发送消息确认机制
         *     channel.basicPublish(exchange,queue,routingKey,queueMsg.getBytes(StandardCharsets.UTF_8));
         *     channel.waitForConfirms())
         *     2.2 channel.waitForConfirmsOrDie(); 批量confirm确认机制
         *     channel.confirmSelect();
         *     for (int i=0;i<10;i++){
         *          channel.basicPublish(exchange,queue,routingKey,queueMsg.getBytes(StandardCharsets.UTF_8));
         *     }
         *     channel.waitForConfirmsOrDie();
         *     2.3 channel.addConfirmListener 异步监听confirm机制
         *     channel.confirmSelect();
         *         for (int i=0;i<10;i++){
         *             channel.basicPublish(exchange,queue,routingKey,queueMsg.getBytes(StandardCharsets.UTF_8));
         *         }
         *         // confirm机制
         *         channel.addConfirmListener(new ConfirmListener() {
         *             @Override
         *             public void handleAck(long l, boolean b) throws IOException {
         *                 System.out.println("已确认消息: "+l);
         *             }
         *
         *             @Override
         *             public void handleNack(long l, boolean b) throws IOException {
         *                 System.out.println("未确认消息: "+l);
         *             }
         *         });
         */
        channel.confirmSelect();
        // confirm机制
        for (int i=0;i<1000;i++){
             channel.basicPublish(exchange,queue,null,queueMsg.getBytes(StandardCharsets.UTF_8));
        }
        channel.waitForConfirmsOrDie();
        channel.close();
        connection.close();
    }

    /**
     * Publish/subscribe(交换机类型:Fanout,也称为广播 )
     * 交换机只负责消息的转发不负责消息的存储 发送到交换机中不再需要队列
     */
    public void fanout() throws IOException, TimeoutException {
        Channel channel = connection.createChannel();
        channel.exchangeDeclare(exchange,exchangeType);
        channel.basicPublish(exchange,"",null,queueMsg.getBytes(StandardCharsets.UTF_8));
        channel.close();
        connection.close();
    }

    /**
     * routing 路由发送消息模式
     * @throws IOException
     */
    public void routingProducer() throws IOException, TimeoutException {
        // 1、创建连接队列
        Channel channel = connection.createChannel();
        // 2、创建交换 指定交换机名称和类型 类型为路由模式
        channel.exchangeDeclare(exchange, exchangeType);
        channel.txSelect(); // 3、开始事务 保证消息发送的可靠性防止消息的丢失
        // 4、管道队列初始化 指定交换机 对列或routingKey queueMsg 消息
        try {
            channel.basicPublish(exchange,routingKey,null,queueMsg.getBytes(StandardCharsets.UTF_8));
            channel.txCommit();
        }catch (Exception ex){
            channel.txRollback(); // 事务提交失败后进行回滚
        }finally {
            channel.close(); // 5、关闭连接管道和连接
            connection.close();
        }
    }

    /**
     * topic 模式 设置绑定交换机类型为 topic 并向该交换机中推送数据
     * @throws IOException
     * @throws InterruptedException
     */
    public void topicProducer() throws IOException, InterruptedException {
        Channel channel = connection.createChannel();
        // 绑定交换机
        channel.exchangeDeclare(exchange,exchangeType);
        channel.confirmSelect(); //开启消息自动确认机制
        channel.basicPublish(exchange,routingKey, MessageProperties.PERSISTENT_TEXT_PLAIN,queueMsg.getBytes(StandardCharsets.UTF_8));
        channel.waitForConfirms();
    }
}
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Connection;
import common.projects.devlop.ProducerApplication;
import common.projects.devlop.utils.MsgQue;
import common.projects.devlop.utils.ProducerSendMsg;
import common.projects.devlop.utils.RabbitMqCon;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

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

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class Test {

    // 建立rabbitmq连接
    @org.junit.Test
    public void  connection() throws IOException, TimeoutException {
        Connection connection = RabbitMqCon.builder()
                .host("127.0.0.1")
                .port(5672)
                .timeout(3000)
                .username("guest")
                .virtual("/")
                .password("guest")
                .build().getConnection();
        System.out.println(connection);
    }

    /**
     * worker 工作队列 需要设置对列参数 如 对列名称 是否持久化存储数据 是否独占连接 是否自动删除 额外参数等设置 不需要设置交换机 和 路由key等消息
     * 持久化数据 rabbitmq服务器重启以后对列仍然存在不会出现消息丢失的情况
     * 独占连接 只能有本地连接管道才能操作该对列中的数据 如果该连接断开则对列自动删除
     * 是否自动删除 该对列为空的时候自动删除该对列 可以配置 独占连接实现一个临时对列
     * 额外参数 类型为Map<String,Object> 可以设置对列过期时间等
     * @throws IOException
     * @throws TimeoutException
     * @throws InterruptedException
     */
    @org.junit.Test
    public void sendMsg() throws IOException, TimeoutException, InterruptedException {
        Connection connection = RabbitMqCon.builder()
                .host("127.0.0.1")
                .port(5672)
                .timeout(3000)
                .username("guest")
                .virtual("/")
                .password("guest")
                .build().getConnection();
        ProducerSendMsg.builder()
                .connection(connection)
                .queue(MsgQue.QUEUE_NAME.getQueueName())
                .durable(true)
                .exclusive(false)
                .autoDelete(false)
                .arguments(null)
                .queueMsg("你好啊,小傻瓜")
                .build().sendMsg();
    }

    /**
     * FANOUT 发布订阅机制 需要绑定交换机 不需要绑定对列 交换机只负责转发消息 不存储消息
     * 消费者消费的时候 需要绑定对列和交换机 可以存在多个消费者
     * @throws IOException
     * @throws TimeoutException
     */
    @org.junit.Test
    public void tes() throws IOException, TimeoutException {
        Connection connection = RabbitMqCon.builder()
                .host("127.0.0.1")
                .port(5672)
                .timeout(3000)
                .username("guest")
                .virtual("/")
                .password("guest")
                .build().getConnection();
        ProducerSendMsg.builder().queueMsg("你好啊小傻瓜!").
                exchange("EXCHANGE_NAME")
                .connection(connection)
                .exchangeType(BuiltinExchangeType.FANOUT)
                .build().fanout();
    }

    /**
     * 路由对列 Routing 路由模型(交换机类型:direct)需要绑定交换机 和 routerKey
     * 不需要设置消息对列 交换机只负责转换消息 不存储消息
     *  消费者可以有多个 但是需要绑定交换机 对列 和routerKey
     * @throws IOException
     * @throws TimeoutException
     */
    @org.junit.Test
    public void routingProducer() throws IOException, TimeoutException {
        Connection connection = RabbitMqCon.builder()
                .host("127.0.0.1")
                .port(5672)
                .timeout(3000)
                .username("guest")
                .virtual("/")
                .password("guest")
                .build().getConnection();
        ProducerSendMsg.builder().queueMsg("你好啊小傻瓜!").
                exchange("EXCHANGE_NAME_ROUTING")
                .routingKey("msg")
                .connection(connection)
                .exchangeType(BuiltinExchangeType.DIRECT)
                .build().fanout();
    }

    /**
     * topic 通配符格式
     * * 代表一个通配符 只能有一个参数
     * # 代表后面可以有多个参数
     * @throws IOException
     * @throws TimeoutException
     * @throws InterruptedException
     */
    @org.junit.Test
    public void topicProducer() throws IOException, TimeoutException, InterruptedException {
        Connection connection = RabbitMqCon.builder()
                .host("127.0.0.1")
                .port(5672)
                .timeout(3000)
                .username("guest")
                .virtual("/")
                .password("guest")
                .build().getConnection();
        ProducerSendMsg.builder().queueMsg("你好啊小傻瓜!").
                exchange("EXCHANGE_NAME_Topic")
                .routingKey("exchange.rabbitmq.li")
                .connection(connection)
                .exchangeType(BuiltinExchangeType.DIRECT)
                .build().topicProducer();
    }
}

消费者消费消息

package common.projects.devlop.utils;

import com.rabbitmq.client.*;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.concurrent.TimeoutException;

@Data
@AllArgsConstructor
@Builder
@NoArgsConstructor
public class ConsumerMsg {

    @ApiModelProperty(value = "连接rabbitmq客户端")
    private Connection connection;

    @ApiModelProperty(value = "消息队列名称")
    private String queueName;

    @ApiModelProperty(value = "是否持久化队列存储")
    private Boolean durable;

    @ApiModelProperty(value = "是否独占连接")
    private Boolean exclusive;

    @ApiModelProperty(value = "是否自动删除")
    private Boolean autoDelete;

    @ApiModelProperty(value = "设置额外参数")
    private Map<String,Object> arguments;

    @ApiModelProperty(value = "交换机")
    private String exchange;

    @ApiModelProperty(value = "routingKey")
    private String routerKey;

    @ApiModelProperty(value = "是否手动消费 设置ack")
    private Boolean autoConsume;

    /**
     * worker消息模式
     * @throws IOException
     */
    public void consumer() throws IOException {
            Channel channel = connection.createChannel();
            /**
             * 参数说明
             * queueName 队列名称
             * durable 是否连接持久化 如果设置为true 该列队为空或者断开后重新连接以后 队列不会消失
             * exclusive 是否独占连接 如果设置为独占连接 该对列只能在本地连接中使用 则对列为空时自动删除 设置为true可以设置为临时对列 需要配合 autoDelete使用
             * autoDelete 是否自动删除 如果该对列为空则自动删除
             * arguments 额外配置参数 可配置对列的存活时间
             */
            channel.queueDeclare(queueName,durable,exclusive,autoDelete,arguments);
            DefaultConsumer defaultConsumer = new DefaultConsumer(channel){

                @Override
                /**
                 * consumerTag 消费者标签 用来标识消费者的身份信息 例如 admin
                 * envelope 信封
                 * properties 消息属性
                 * body 消息主体
                 */
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    //交换机
                    String exchange = envelope.getExchange();
                    // body 即消息体
                    String msg = new String(body,"utf-8");
                    System.out.println(" [x] received : " + msg + "!");
                    if(autoConsume){
                        /**
                         * 手动消费ack
                         * multiple:是否批量.true:将一次性ack所有小于deliveryTag的消息。
                         * envelope.getDeliveryTag(): 消息id,mq在channel中用来标识消息的id,可用于确认消息已接收
                         */
                        channel.basicAck(envelope.getDeliveryTag(), false);
                    }
                }
            };
            // 判断是否手动消费ack
            if(autoConsume){
                channel.basicConsume(queueName,false,defaultConsumer); //手动确认ack
                System.out.println("手动消费");
            }else {
                channel.basicConsume(queueName,true,defaultConsumer); //默认自动确认ack
                System.out.println("自动消费");
            }
    }

    /**
     * 发布订阅机制监听消费消息 也称为广播
     * @throws IOException
     */
    public void fanout() throws IOException {
        Channel channel = connection.createChannel();
        channel.queueDeclare(queueName,durable,exclusive,autoDelete,arguments);
        channel.queueBind(queueName,exchange,"");
        DefaultConsumer consumer = new DefaultConsumer(channel){
            @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    // body 即消息体
                    String msg = new String(body);
                    System.out.println(" [邮件服务] received : " + msg + "!");
                }
        };
        channel.basicConsume(queueName,true,consumer);
    }

    /**
     * routing路由模式消费消息
     */
    public void routingConsumer() throws IOException, TimeoutException {
        // 1、创建消费者连接通道
        Channel channel = connection.createChannel();
        channel.queueDeclare(queueName,durable,exclusive,autoDelete,arguments);
        // 2、绑定管道初始化 绑定 交换机 对列 routerKey
        channel.queueBind(queueName,exchange,routerKey);
        DefaultConsumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                // body 即消息体
                String msg = new String(body);
                System.out.println(" [邮件服务] received : " + msg + "!");
            }
        };
        channel.basicConsume(queueName,true,consumer); // 消费者消费 绑定对列 ack设置为自动消费 默认消费消息
        channel.close();
        connection.close();
    }

    /**
     * 通配符消费消息
     * * 代表后面跟一个参数
     * # 代码后面可以跟多个参数
     */
    public void topic_consumer() throws IOException {
        Channel channel = connection.createChannel();
        channel.queueDeclare(queueName,durable,exclusive,autoDelete,arguments);
        // 绑定消息队列 交换机通配符
        channel.queueBind(queueName,exchange,routerKey);
        // 创建消息默认消费
        DefaultConsumer consumer = new DefaultConsumer(channel){

            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String msg = new String(body,"utf-8");
                System.out.println("消费者消息为: "+msg);
            }
        };
        channel.basicConsume(queueName,true,consumer);
    }
}
import com.rabbitmq.client.Connection;
import common.projects.devlop.ConsumerApplication;
import common.projects.devlop.utils.ConsumerCon;
import common.projects.devlop.utils.ConsumerMsg;
import common.projects.devlop.utils.MsgQue;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

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

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ConsumerApplication.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ConsumerTest {

    @Test
    public void test() throws IOException, TimeoutException {
        Connection connection = ConsumerCon.builder()
                .host("127.0.0.1")
                .port(5672)
                .timeout(3000)
                .username("guest")
                .virtual("/")
                .password("guest")
                .build().getCon();
        ConsumerMsg.builder()
                .connection(connection)
                .queueName(MsgQue.QUEUE_NAME.getQueueName())
                .durable(true)
                .exclusive(false)
                .autoDelete(false)
                .arguments(null)
                .autoConsume(true)
                .build().consumer();
    }


    @Test
    public void tests() throws IOException, TimeoutException {
        Connection connection = ConsumerCon.builder()
                .host("127.0.0.1")
                .port(5672)
                .timeout(3000)
                .username("guest")
                .virtual("/")
                .password("guest")
                .build().getCon();
        ConsumerMsg.builder()
                .connection(connection)
                .queueName(MsgQue.QUEUE_NAME.getQueueName())
                .durable(true)
                .exclusive(false)
                .autoDelete(false)
                .arguments(null)
                .autoConsume(false)
                .build().consumer();
    }


    @Test
    public void fanoutConsumer() throws IOException, TimeoutException {
        Connection connection = ConsumerCon.builder()
                .host("127.0.0.1")
                .port(5672)
                .timeout(3000)
                .username("guest")
                .virtual("/")
                .password("guest")
                .build().getCon();
        ConsumerMsg.builder()
                .connection(connection)
                .queueName("QUEUEName")
                .exchange("EXCHANGE_NAME")
                .durable(false)
                .exclusive(false)
                .autoDelete(false)
                .arguments(null)
                .autoConsume(false)
                .build().fanout();
    }

    @Test
    public void fanoutConsumers() throws IOException, TimeoutException {
        Connection connection = ConsumerCon.builder()
                .host("127.0.0.1")
                .port(5672)
                .timeout(3000)
                .username("guest")
                .virtual("/")
                .password("guest")
                .build().getCon();
        ConsumerMsg.builder()
                .connection(connection)
                .queueName("QUEUENAME")
                .exchange("EXCHANGE_NAME")
                .durable(false)
                .exclusive(false)
                .autoDelete(false)
                .arguments(null)
                .autoConsume(false)
                .build().fanout();
    }


    @Test
    public void routingConsumer() throws IOException, TimeoutException {
        Connection connection = ConsumerCon.builder()
                .host("127.0.0.1")
                .port(5672)
                .timeout(3000)
                .username("guest")
                .virtual("/")
                .password("guest")
                .build().getCon();
        ConsumerMsg.builder()
                .connection(connection)
                .queueName("QUEUENAME_routing")
                .exchange("EXCHANGE_NAME_ROUTING")
                .durable(false)
                .exclusive(false)
                .autoDelete(false)
                .arguments(null)
                .autoConsume(false)
                .routerKey("msg")
                .build().routingConsumer();
    }

    @Test
    public void topic_consumer() throws IOException, TimeoutException {
        Connection connection = ConsumerCon.builder()
                .host("127.0.0.1")
                .port(5672)
                .timeout(3000)
                .username("guest")
                .virtual("/")
                .password("guest")
                .build().getCon();
        ConsumerMsg.builder()
                .connection(connection)
                .queueName("QUEUENAME_topic")
                .exchange("EXCHANGE_NAME_Topic")
                .durable(false)
                .exclusive(false)
                .autoDelete(false)
                .arguments(null)
                .autoConsume(false)
                .routerKey("*.*.li")
                .build().topic_consumer();
    }

    @Test
    public void list() throws IOException, TimeoutException {
        test();
        tests();
    }
}

第一问:
生产者是如何避免消息丢失的
1、开启rabbitmq的事务机制

           rabbitmq生产者数据丢失问题解决方法
         * 1、声明开启mq事务 保证生产者数据的完性 由于事务开启和事务关闭的两个速度差为149倍 一般很少使用rabbitmq事务
         *        try {
         *           channel.txSelect(); // 1.1、声明开启一个事务
         *           channel.basicPublish(exchange,queue,routingKey,queueMsg.getBytes(StandardCharsets.UTF_8));
         *           channel.txCommit(); // 1.2、事务的提交
         *        }catch (Exception ex){
         *           channel.txRollback(); // 1.3、发生错误事务回滚
         *        }finally {
         *           // 3、关闭通道和客户端的连接
         *           channel.close();
         *           connection.close();
         *        }

2、开启生产者消息确认机制 confirm

 2、confirm发送方确认机制  confirm的三种确认机制
         *     2.1 channel.waitForConfirms() 普通confirm普通消息机制
         *     channel.confirmSelect(); //开启confirm发送消息确认机制
         *     channel.basicPublish(exchange,queue,routingKey,queueMsg.getBytes(StandardCharsets.UTF_8));
         *     channel.waitForConfirms())
         *     2.2 channel.waitForConfirmsOrDie(); 批量confirm确认机制
         *     channel.confirmSelect();
         *     for (int i=0;i<10;i++){
         *          channel.basicPublish(exchange,queue,routingKey,queueMsg.getBytes(StandardCharsets.UTF_8));
         *     }
         *     channel.waitForConfirmsOrDie();
         *     2.3 channel.addConfirmListener 异步监听confirm机制
         *     channel.confirmSelect();
         *         for (int i=0;i<10;i++){
         *             channel.basicPublish(exchange,queue,routingKey,queueMsg.getBytes(StandardCharsets.UTF_8));
         *         }
         *         // confirm机制
         *         channel.addConfirmListener(new ConfirmListener() {
         *             @Override
         *             public void handleAck(long l, boolean b) throws IOException {
         *                 System.out.println("已确认消息: "+l);
         *             }
         *
         *             @Override
         *             public void handleNack(long l, boolean b) throws IOException {
         *                 System.out.println("未确认消息: "+l);
         *             }
         *         });

第二问:
如何避免消息积压

采用worker工作消息队列,多个worker操作同一个queue
然后采用线程池异步对消息进行消费可以有效的避免消息的积压

第三问:

如何保证消息不丢失
消费者端采用ack机制可以将消息持久化存储,前提是交换机和消息队列必须先设置为持久化存储
消息发布方设置 exchange为持久化存储
 channel.exchangeDeclare(exchange, exchangeType,true);
 消息发布方设置 消息为持久化存储channel.basicPublish(exchange,routingKey,MessageProperties.PERSISTENT_TEXT_PLAIN,queueMsg.getBytes(StandardCharsets.UTF_8));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pursue?????

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值