ActiveMQ:学习笔记

Table of Contents

一、linux 安装activemq及应用

二、JMS

一组成:

二 消息可靠性 : (持久性  ,事务,  签收)

 1 persisent 持久性:messageProducer.setDeliverymodel(DeliveryModel.NOO_PERSISENT);//非持久化

  2 事务

 3 acknowledge 签收

总结:

四、spring整合activemq

五、SpringBoot整合Activemq

1 队列:

2:发布订阅

 topic生产者:

topic消费者:

六、AcitveMQ传输协议 

tcp语法:tcp://hostname:port?key=value

 NIO 传输人协议:

七 activemq持久化

 JDBC持久化JDBC persistence.演示

jdbc with  journal  演示

八、ActiveMQ集群

九、高级特性



  • 一、linux 安装activemq及应用

https://activemq.apache.org/官网下载apache-activemq-5.15.9-bin.tar.gz  用xftp上传到/opt目录解压在bin目录中启动./activemq start   ,前提是需要对应jdk版本(我安装是对应需要jdk1.8)

查看启动:
启动 bin下面的命令
./activemq start

默认后台端口61616 前台端口8161
查看是否启动三种方式
1  netstat -anp |grep 61616
2  ps -er | grep activemq | grep -v grep
3  lsof -i:61616

 

ActiveMQ:学习笔记_第1张图片

 

两个模式:queue和topic

ActiveMQ:学习笔记_第2张图片

两个模式的差异

ActiveMQ:学习笔记_第3张图片

 

 

 

javaee

ActiveMQ:学习笔记_第4张图片

JMS

ActiveMQ:学习笔记_第5张图片

  • 二、JMS

一组成:


JMS    组成结构和特点
provide 服务器
produce 生产者
consumer 消费者
message :消息头,消息体,消息属性


JMS message
消息头:几个重要的设置
JMSDestination 目的地:发送消息的目的地主要指Queue和Topic
JMSDeliveryModel  持久和非持久
JMSExpiration  消息过期设置
JMSPriority    消息优先级
JMSMessageID   消息唯一标志id:唯一识别每个消息的标志由mq产生

ActiveMQ:学习笔记_第6张图片

 ActiveMQ:学习笔记_第7张图片

ActiveMQ:学习笔记_第8张图片

消息体 :封装具体的消息数据
5种消息体格式:
TextMessage 普通的字符串包含一个String
MapMessage  一个Map类型消息,key是String 而值是java基本类型
BytesMessage  二进制数组消息,包含一个byte[]
StreamMessage  java数据流消息,用标准的流操作来顺序填充和读取
ObjectMess age   对象消息,包含一个可序列化的java对象
发送和接收消息体类型必须一致对应
 

消息属性
如果需要除消息头字段以外的值,那么可以使用消息属性
识别/去重/重点标注等操作非常有用的方法
是一对kv对:如 textMessage.setStringProperty("c01","vip");
 


二 消息可靠性 : (持久性  ,事务,  签收)

 1 persisent 持久性:messageProducer.setDeliverymodel(DeliveryModel.NOO_PERSISENT);//非持久化

       DeliveryModel.PERSISENT持久化 默认策略就是持久化
     持久化topic:一定要先运行一次消费者等于是想mq注册,类似订阅了这个主题,然后再运行生产者发送消息
       此时无论消费者是否在线都会接收到消息,不在线的话下次连接时候会把没有接收过的消息都接收回来。


       队列:1 非持久性演示:当服务器宕机 ,消息依然存在
                  2 持久性演示:当服务器宕机,消息依然存在
                 3 队列默认策略就是持久化

    topic:持久化演示

             一定先运行一次消费者,等于向mq注册,类似我们订阅了这个主题,然后再运行生产者发送消息
             此时,无论消费者是否在线,都会接受到,不在线的话,下次连接时候会把没有接收的消息都接收下来
       

----订阅者 
 private static final String URL_BROKER = "tcp://192.168.163.131:61616";
    private static final String TOPIC_NAME = "topic_persisent";
    public static void main(String[] args) throws JMSException, IOException {
        System.out.println("我是余斌号消费者");
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
        Connection connection = activeMQConnectionFactory.createConnection();
        //指定客户端是哪个订阅了
        connection.setClientID("余斌");

        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建目的地tipic
        Topic topic = session.createTopic(TOPIC_NAME);

        //创建持久的订阅者 Subscribers  是订阅哪个主题topic
        TopicSubscriber durableSubscriber = session.createDurableSubscriber(topic, "描述信息。。。");

        connection.start();

        //主题的订阅者接收
        Message message = durableSubscriber.receive();
        while (message != null) {
            TextMessage textMessage = (TextMessage) message;
            System.out.println("接收持久化的topic 消息:"+textMessage.getText());
            message =durableSubscriber.receive(3000L);
        }


        session.close();
        connection.close();
        System.out.println("消息接收完毕!");

--事务偏生产者,签收偏消费者

  2 事务

      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    
    如果是false:只要执行send就进入到队列中去,关闭事务,那么第二个签收参数设置需要有效
    如果是true,先执行send在执行commit,消息才被真正提交到队列中,消息需要批量发送需要缓冲区处理

  生产者--------如果是false 则send的时候就提交成功到目的地,如果是true,一定需要提交commit,出错可以回滚rollback,如果没有commit那么消息就没有发送到目的地。

消费者 ---------如果设置为false,则消息只被消费一次,如果是true,一定需要设置commit,如果没有写commit那么消息会被重复消费,


 3 acknowledge 签收

 

非事务下的签收: 
    1 自动签收(默认)
    2 手动签署 :需要显示的调用acknowledge方法,如 textMessage.acknowledge();
    3 可重复签收:了解即可

事务下的签收
    生产事务开始,只有commit后才能将全部消费变为已消费
    当一个事务被成功提交则消息被自动签收,如果事务回滚,则消息会被再次传送,
    
    事务与签收的关系:事务比签收更大,只要是开始事务,不管有没有显示调用acknowledge方法,只要提交就默认是自动签收
    如果开启事务但是没有commit调用,即使写了acknowledge方法签收也不会成功。
    
非事务会话中,消息何时被确认取决于创建会话时候的应答模式(acknowledgement model),如果自动签收就自动,如果手动签收就需要调用textMessage.acknowledge();
     

总结:

队列

ActiveMQ:学习笔记_第9张图片

topic 

ActiveMQ:学习笔记_第10张图片 非持久订阅

private static final String URL_BROKER = "tcp://192.168.163.131:61616";
    private static final String TOPIC_NAME = "topic_01";
    public static void main(String[] args) throws JMSException, IOException {
        System.out.println("我是1号消费者");
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
        Connection connection = activeMQConnectionFactory.createConnection();

        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        Topic topic = session.createTopic(TOPIC_NAME);

        MessageConsumer consumer = session.createConsumer(topic);

        consumer.setMessageListener(message -> {
            if(null != message && message instanceof TextMessage) {
                TextMessage textMessage = (TextMessage) message;
                try {
                    System.out.println("接收消息:"+textMessage.getText());
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            if(null != message && message instanceof MapMessage) {
            MapMessage mapMessage = (MapMessage) message;
            try {
                String k1 = mapMessage.getString("k1");
                System.out.println("接收消息:"+k1);

            } catch (JMSException e) {
                e.printStackTrace();
            }
            }
        });
        System.in.read();
        consumer.close();
        session.close();
        connection.close();
        System.out.println("消息接收完毕!");
    }

ActiveMQ:学习笔记_第11张图片 持久订阅

private static final String URL_BROKER = "tcp://192.168.163.131:61616";
    private static final String TOPIC_NAME = "topic_persisent";
    public static void main(String[] args) throws JMSException, IOException {
        System.out.println("我是余斌号消费者");
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
        Connection connection = activeMQConnectionFactory.createConnection();
        //指定客户端是哪个订阅了
        connection.setClientID("余斌");

        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建目的地tipic
        Topic topic = session.createTopic(TOPIC_NAME);

        //创建持久的订阅者 Subscribers  是订阅哪个主题topic
        TopicSubscriber durableSubscriber = session.createDurableSubscriber(topic, "描述信息。。。");

        connection.start();

        //主题的订阅者接收
        Message message = durableSubscriber.receive();
        while (message != null) {
            TextMessage textMessage = (TextMessage) message;
            System.out.println("接收持久化的topic 消息:"+textMessage.getText());
            message =durableSubscriber.receive(3000L);
        }


        session.close();
        connection.close();
        System.out.println("消息接收完毕!");



    }

 ActiveMQ:学习笔记_第12张图片

 必须签收用持久订阅,当丢失消息能够被容忍,则用非持久订阅

 

三、linux启动不同的配置文件(类似redis)

./activemq start xbean:file:/myactivemq/conf/activemq02.xml

ActiveMQ:学习笔记_第13张图片

启动本地idea中的broker

 

 public static void main(String[] args) throws Exception {
        BrokerService brokerService = new BrokerService();
        brokerService.setUseJmx(true);
        brokerService.addConnector("tcp://localhost:61616");
        brokerService.start();
    }

G:\360Downloads\workspace201907\activemq>jps -l
3280 com.yubin.cn.activemq.Embed.EmbedBroker
6464 sun.tools.jps.Jps
1044 org.jetbrains.jps.cmdline.Launcher
5304 org.jetbrains.idea.maven.server.RemoteMavenServer
4284

G:\360Downloads\workspace201907\activemq>
 

 

四、spring整合activemq





    

    
        
            
                
            
        
        
    

    
        
    

    
        
    

    
        
        
        
        
    
    


    
        
        
        
    

ActiveMQ:学习笔记_第14张图片

写实现MessageListener一个监听器的类 :可以实现不启动消费者只启动生产者就可以接收到消息(可以监听队列或者topic,只需要配置监听程序中将队列换成topic就可以)


@Component
public class MyMessageListener implements MessageListener {
    @Override
    public void onMessage(Message message) {
        if(null != message && message instanceof TextMessage) {
            TextMessage textMessage = (TextMessage) message;

            try {
                System.out.println("监听到的消息为:"+textMessage.getText());
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    }
}

 

五、SpringBoot整合Activemq

  1. 1 队列:

ActiveMQ:学习笔记_第15张图片

//消息生产者主要代码
@Component
public class Queue_Producer {

    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    @Autowired
    private Queue queue;

    public void producerMsg() {
        jmsMessagingTemplate.convertAndSend(queue,"******:"+UUID.randomUUID().toString().substring(0,6));

    }

    //间隔三秒往Mq推送消息以达到定时发送case,案例
    @Scheduled(fixedDelay= 3000L )
    public void produceMsgScheduled() {
        jmsMessagingTemplate.convertAndSend(queue,"******Scheduled:"+UUID.randomUUID().toString().substring(0,6));
        System.out.println("produceMsgScheduled send ok ");

    }

}

 

 

ActiveMQ:学习笔记_第16张图片

//消息消费者部分代码
@Component
public class Queue_Consumer {

    @JmsListener(destination = "${myqueue}")
    public void receive(TextMessage textMessage) throws  JMSException {

        System.out.println("监听到的消息为:"+textMessage.getText());

    }
}

 使用jmsMessagetemplete生产消息,使用receive或者配置监听器消费消息。

 

  1. 2:发布订阅

ActiveMQ:学习笔记_第17张图片

ActiveMQ:学习笔记_第18张图片

 topic生产者:

application.yml配置文件:
server:
  port: 6666
spring:
  activemq:
    broker-url: tcp://192.168.163.131:61616
    user: admin
    password: admin
  jms:
    pub-sub-domain: true


#配置自己的自定义topic
mytopic: springboot-activemq-topic
***********************************************************

配置bean类
@Component
public class confBean {

    @Value("${mytopic}")
    private String topicName;

    @Bean
    public Topic topic() {
        return new ActiveMQTopic(topicName);
    }
}

***********************************************************
定时任务生产消息

@Component
public class Topic_Producer {

    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    @Autowired
    private Topic topic;

    @Scheduled(fixedDelay = 3000L)
    public void producerTopic() {
        jmsMessagingTemplate.convertAndSend(topic,"主题topic生产消息:"+UUID.randomUUID().toString().substring(0,6));
        System.out.println("topic producer send end");
    }
}

topic消费者:

application.yml配置文件
server:
  port: 5567 #5567
spring:
  activemq:
    broker-url: tcp://192.168.163.131:61616
    user: admin
    password: admin
  jms:
    pub-sub-domain: true



#配置自己的自定义topic
mytopic: springboot-activemq-topic
*************************************************

消费者消费消息:

@Component
public class Topic_Consumer {

    @JmsListener(destination = "${mytopic}")
    public void receiveTopic(TextMessage textMessage) throws JMSException {
        System.out.println("topic消费者接收消息:"+textMessage.getText());
    }
}

六、AcitveMQ传输协议 

ActiveMQ:学习笔记_第19张图片

ActiveMQ:学习笔记_第20张图片

ActiveMQ:学习笔记_第21张图片

tcp语法:tcp://hostname:port?key=value

参数可选的有可以参考官网:https://activemq.apache.org/tcp-transport-reference

ActiveMQ:学习笔记_第22张图片

 

 NIO 传输人协议:

ActiveMQ:学习笔记_第23张图片

ActiveMQ:学习笔记_第24张图片

 

amqp:

ActiveMQ:学习笔记_第25张图片

 

stomp:协议

ActiveMQ:学习笔记_第26张图片 

 

SSL协议

ActiveMQ:学习笔记_第27张图片

mqtt协议:

ActiveMQ:学习笔记_第28张图片

ActiveMQ:学习笔记_第29张图片

ws协议

ActiveMQ:学习笔记_第30张图片

总结:

ActiveMQ:学习笔记_第31张图片

NIO案例:

消息生产者
public class JmsProduce {

//    private static final String URL_BROKER = "tcp://192.168.163.131:61616";
//    private static final String URL_BROKER = "tcp://localhost:61616";
private static final String URL_BROKER = "nio://192.168.163.131:61618";
    private static final String QUEUE_NAME = "queue1";

    public static void main(String[] args) throws JMSException {
        //创建连接工厂
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
        //创建连接
        Connection connection = activeMQConnectionFactory.createConnection();
        connection.start();
        //获取session
        Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
        //声明队列
        Queue queue = session.createQueue(QUEUE_NAME);
        //创建生产者
        MessageProducer producer = session.createProducer(queue);

        for(int i = 1;i<=3;i++) {
            TextMessage textMessage = session.createTextMessage("msg_" + i);
            //设置消息属性
            textMessage.setStringProperty("c01","vip");

            producer.send(textMessage);
        }

        session.commit();
        producer.close();
        session.close();
        connection.close();

        System.out.println("消息发送完毕!");

    }
}
**************************************************

消息消费者
//    private static final String URL_BROKER = "tcp://192.168.163.131:61616";
//    private static final String URL_BROKER = "tcp://localhost:61616";
private static final String URL_BROKER = "nio://192.168.163.131:61618";
    private static final String QUEUE_NAME = "queue1";
    public static void main(String[] args) throws JMSException, IOException {
        System.out.println("我是2号消费者");
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
        Connection connection = activeMQConnectionFactory.createConnection();

        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        Queue queue = session.createQueue(QUEUE_NAME);




        MessageConsumer consumer = session.createConsumer(queue);

        // 方式一  receive
/*
        //订阅者或者接受者MessageConsumer的receive方法来接收消息,receive在能够接收的消息前将一直阻塞
        while(true) {
            //receive可以接收参数,可以指定等待时间,过时不候 Message receive(long timeout)
            TextMessage receive = (TextMessage)consumer.receive();
            if(null != receive) {
                System.out.println("接收消息:"+receive.getText());
            }else {

                break;
            }
        }

        consumer.close();
        session.close();
        connection.close();*/


        //方式二  监听MessageListener
//        异步非阻塞方式(监听onMessage())
//        订阅者或者消息接受者MessageConsumer的setMessageListener(MessageLinstener listener)
//        注册一个消息监听,当消息到达后,系统自动调用监听器的监听方法

        consumer.setMessageListener(new MessageListener() {
            public void onMessage(Message message) {
                if(null != message && message instanceof TextMessage) {
                    TextMessage textMessage = (TextMessage) message;
                    try {
                        System.out.println("接收消息:"+textMessage.getText());
                        System.out.println("接收消息:"+textMessage.getStringProperty("c01"));//获取消息属性
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        System.in.read();
        consumer.close();
        session.close();
        connection.close();
        System.out.println("消息接收完毕!");



    }
}

NIO增强改进

ActiveMQ:学习笔记_第32张图片

ActiveMQ:学习笔记_第33张图片

 

七 activemq持久化

ActiveMQ:学习笔记_第34张图片

ActiveMQ:学习笔记_第35张图片

ActiveMQ:学习笔记_第36张图片

ActiveMQ:学习笔记_第37张图片

ActiveMQ:学习笔记_第38张图片 ActiveMQ:学习笔记_第39张图片

ActiveMQ:学习笔记_第40张图片

 

leaelDB:消息存储(了解)

步骤:

jar包:mysql-connector-java-5.1.38.jar

ActiveMQ:学习笔记_第41张图片

ActiveMQ:学习笔记_第42张图片

 JDBC持久化JDBC persistence.演示

ActiveMQ:学习笔记_第43张图片

连接池的配置:

ActiveMQ:学习笔记_第44张图片

queue队列演示jdbc持久化结果

ActiveMQ:学习笔记_第45张图片

发布订阅topic持久化演示: activemq_acks表中存有信息,msg中消费成功也不会删除,会归档,相当于订阅后可以查看之前的历史

 ActiveMQ:学习笔记_第46张图片

 

消息jdbc持久化总结和开发坑
 如果queue,在没有消费者消费的情况下将消息保存到activemq_msgs表中。只要有任意一个消费者已经消费过,消费之后这些消息将会立即被删除。
 
 如果是topic,一般先启动消费者订阅然后再生产的情况下会将消息保存到activemq_acks;
 
 坑:
 在配置关系型数据库作为activemq的持久化存储方案时候的坑,
 数据库jar包,记得需要使用相关jar文件放在在activemq安装路径下lib目录下,mysql-jdbc驱动的jar包和对应的数据库连接池jar包
 
 crateTablesOnStartup 属性
 在jadbPersistenceAdapter标签中设置这个属性为true时在第一次启动activemq时候,activemq服务节点会自动创建所需要数据表。启动完成后可以去掉这个属性或者更改为false;
 
 
 下划线坑爹。
 “java.lang.IllegalStateException.BeanFactory.notinitialized or aleardy closed”
 
 这个是因为您在操作系统的机器名中有“_”符号,请修改机器名并且重启后即可解决

 

jdbc with  journal  演示

带高速缓存日志功能的jdbc 持久

ActiveMQ:学习笔记_第47张图片


	

 

ActiveMQ:学习笔记_第48张图片

相当于在mysql数据库前面当了一层journal高速缓存,有数据先从journal中存着,如果七八分钟没有消费就慢慢写入mysql,消费也先从journal消费,然后等七八分钟后同步到mysql,将myslq中删除,有点读写分离的样子。 

ActiveMQ:学习笔记_第49张图片

八、ActiveMQ集群

ActiveMQ:学习笔记_第50张图片ActiveMQ:学习笔记_第51张图片

 

ActiveMQ:学习笔记_第52张图片

 

 集群原理图

ActiveMQ:学习笔记_第53张图片

 

九、高级特性

一  异步投递

:指定同步或者非事务情况下发送持久化消息两种情况下是同步的,其他都是异步的

ActiveMQ:学习笔记_第54张图片

官方配置:三种方式

ActiveMQ:学习笔记_第55张图片

 

异步发送如何确定发送成功 :正确的异步发送是需要接收回调的

 ActiveMQMessageProduce 生产者回调方法确定消息发送成功

public class JmsProduce_mianshi_async {

    private static final String URL_BROKER = "tcp://192.168.163.131:61616";

    private static final String QUEUE_NAME = "queue_async";


    public static void main(String[] args) throws JMSException {
        //创建连接工厂
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
        //开启异步投递
        activeMQConnectionFactory.setUseAsyncSend(true);

        //创建连接
        Connection connection = activeMQConnectionFactory.createConnection();
        connection.start();
        //获取session
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //声明队列
        Queue queue = session.createQueue(QUEUE_NAME);
        //创建生产者
        ActiveMQMessageProducer producer = (ActiveMQMessageProducer) session.createProducer(queue);

        for (int i = 1; i <= 3; i++) {
            TextMessage textMessage = session.createTextMessage("msg_" + i);
            textMessage.setJMSMessageID(UUID.randomUUID().toString() + "order yubin");
            String jmsMessageID = textMessage.getJMSMessageID();
            //设置消息属性
//            textMessage.setStringProperty("c01","vip");

            producer.send(textMessage, new AsyncCallback() {
                //异步发送消息:确认发送成功
                @Override
                public void onSuccess() {
                    System.out.println("messageId:" + jmsMessageID + ".消息发送成功");

                }

                @Override
                public void onException(JMSException exception) {
                    System.out.println("消息发送失败");
                }
            });
        }
        producer.close();
        session.close();
        connection.close();

        System.out.println("消息发送完毕!");

    }
}

 

ActiveMQ:学习笔记_第56张图片

 

二、延迟投递和定时投递

 ActiveMQ:学习笔记_第57张图片

四大属性:

ActiveMQ:学习笔记_第58张图片

延迟投递和定时投递使用案例 :步骤

1 broker服务器开启对延迟和定时的支持schedulerSupport="true"

2 代码编写

ActiveMQ:学习笔记_第59张图片

 private static final String URL_BROKER = "tcp://192.168.163.131:61616";

    private static final String QUEUE_NAME = "delayAndSchedule";
    public static void main(String[] args) throws JMSException {
        //创建连接工厂
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
        //创建连接
        Connection connection = activeMQConnectionFactory.createConnection();
        connection.start();
        //获取session
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //声明队列
        Queue queue = session.createQueue(QUEUE_NAME);
        //创建生产者
        MessageProducer producer = session.createProducer(queue);
        //开启消息持久化
        producer.setDeliveryMode(DeliveryMode.PERSISTENT);
        Long dalay = 3 * 1000L;
        Long period = 4 * 1000L;
        int repeat = 5;
        for(int i = 1;i<=3;i++) {
            TextMessage textMessage = session.createTextMessage("msg_" + i);
            //设置消息属性
            textMessage.setStringProperty("c01","vip");

            textMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY,dalay);
            textMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD,period);
            textMessage.setIntProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT,repeat);

            producer.send(textMessage);
        }
        producer.close();
        session.close();
        connection.close();
        System.out.println("消息发送完毕!");

    }

三、Activemq重试机制

https://activemq.apache.org/redelivery-policy

面试题:

具体哪些情况会引起消息重试
说说消息重发时间间隔和重发次数
有毒消息Poison ACK谈谈你的理解

体哪些情况会引起消息重试
答案:
1 client用了transactions并且session调用了rollback()
2 client调用transactions并且调用commit()之前关闭或者没有commit
3 client在client_acknowledeg的传递模式下,sesion调用recover()

说说消息重发时间间隔和重发次数
答案:1秒间隔  重发6次数


有毒的posion ack 谈谈理解
一个消息被redelivedred超过默认做大重发次数(6次)时候,消息端会给ma发送一个posion ack表示这个消息有毒,
告诉break不要再发了,这个时候break会把这个消息放到DLQ(死信队列)
 

重发机制的属性

ActiveMQ:学习笔记_第60张图片

 

//手动配置重发机制,不用默认的
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
redeliveryPolicy.setMaximumRedeliveries(3);
activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);

 

//重试机制,开启事务但是不提交,测试消费六次加第一给 后就不会有消费了

public class JmsConsumer_Redelivery_Policy {
    private static final String URL_BROKER = "tcp://192.168.163.131:61616";

    private static final String QUEUE_NAME = "redleivey_policy";
    public static void main(String[] args) throws JMSException, IOException {
        System.out.println("我是2号消费者");
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);

        //手动配置重发机制,不用默认的
        RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
        redeliveryPolicy.setMaximumRedeliveries(3);
        activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);

        Connection connection = activeMQConnectionFactory.createConnection();

        connection.start();
        Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);

        Queue queue = session.createQueue(QUEUE_NAME);

        MessageConsumer consumer = session.createConsumer(queue);

        // 方式一  receive
/*
        //订阅者或者接受者MessageConsumer的receive方法来接收消息,receive在能够接收的消息前将一直阻塞
        while(true) {
            //receive可以接收参数,可以指定等待时间,过时不候 Message receive(long timeout)
            TextMessage receive = (TextMessage)consumer.receive();
            if(null != receive) {
                System.out.println("接收消息:"+receive.getText());
            }else {

                break;
            }
        }

        consumer.close();
        session.close();
        connection.close();*/


        //方式二  监听MessageListener
//        异步非阻塞方式(监听onMessage())
//        订阅者或者消息接受者MessageConsumer的setMessageListener(MessageLinstener listener)
//        注册一个消息监听,当消息到达后,系统自动调用监听器的监听方法

        consumer.setMessageListener(new MessageListener() {
            public void onMessage(Message message) {
                if(null != message && message instanceof TextMessage) {
                    TextMessage textMessage = (TextMessage) message;
                    try {
                        System.out.println("接收消息:"+textMessage.getText());
                        System.out.println("接收消息:"+textMessage.getStringProperty("c01"));//获取消息属性
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

//        session.commit();
        System.in.read();
        consumer.close();
        session.close();
        connection.close();
        System.out.println("消息接收完毕!");



    }

重发机制整合在spring中的配置

ActiveMQ:学习笔记_第61张图片

 

四、死信队列

ActiveMQ:学习笔记_第62张图片

 

死信队列的应用

ActiveMQ:学习笔记_第63张图片

配置共享和私有的死信队列

shareDeadLetterStrategy,IndvidualDeadLetterStrategy

ActiveMQ:学习笔记_第64张图片

ActiveMQ:学习笔记_第65张图片

配置自动删除过期消息

 ActiveMQ:学习笔记_第66张图片

配置存放非持久性的消息到死信队列

ActiveMQ:学习笔记_第67张图片

 

死信队列配置案例

ActiveMQ:学习笔记_第68张图片

 

 

五、重复消费问题以及幂等性

面试:如何保证消息不被重复消费,幂等性问题的理解

ActiveMQ:学习笔记_第69张图片

你可能感兴趣的:(activemq,activemq)