ActiveMq应用

使用activeMQ的准备工作

1、安装VMware(虚拟机)

​ 安装地址:http://www.mamicode.com/info-detail-3009804.html

2、使用VMware安装Ubuntu和CentOS

​ 安装地址Ubuntu:http://mirrors.163.com/

​ 安装地址CentOS:http://mirrors.163.com/centos/8/isos/x86_64/

3、在VMware上安装Ubuntu

​ 安装步骤参考地址:https://blog.csdn.net/stpeace/article/details/78598333

4、安装ActiveMQ

​ 官网下载地址:http://activemq.apache.org/components/classic/download/

activeMQ

1、特点
  • 高可用
  • 集群和容错配置
  • 持久化
  • 延时发送/定时投递
  • 签收机制
  • spring整合
  • Java语言
2、解决的问题
  • 解耦
  • 异步
  • 削峰
4、方式
  • 队列:点对点模式
  • 主题:发布订阅模式
6、JMS创建编码(queue队列)
(1)pom.xml文件
<dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-all</artifactId>
            <version>5.15.9</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xbean</groupId>
            <artifactId>xbean-spring</artifactId>
            <version>3.16</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
(2)消息生产者编码
public class JmsProduce {
    public static final String ACTIVEMQ_URL="tcp://localhost:61616";
    public static final String QUEUE_NMAE="queue";

    public static void main(String[] args) throws JMSException {
        //1、创建连接工厂,采用默认的用户名和密码
        ActiveMQConnectionFactory activeMQConnectionFactory=new ActiveMQConnectionFactory(ACTIVEMQ_URL);
        //2、通过创建工厂,获得连接connection并启动访问
        Connection connection=activeMQConnectionFactory.createConnection();
        connection.start();
        //3、创建会话session,里面有两个参数:事务和签收
        Session session=connection.createSession(false,Session.AUTO_ACKNOWLEDGE);

        //4、创建目的地(具体时间队列还是主题)
        Queue queue=session.createQueue(QUEUE_NMAE);
        //5、创建消息的生产者
        MessageProducer messageProducer=session.createProducer(queue);
       //持久化数据
        messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);
        //6、通过使用messageProducer产生三条消息发送到mq的队列中
        for(int i=0;i<=3;i++){
            //7、创建消息(好比一个字符串2)
            TextMessage textMessage=session.createTextMessage("msg:"+i);
            //8、通过messageProducer发送给mq
            messageProducer.send(textMessage);
        }
        //9、关闭资源
        messageProducer.close();
        session.close();
        connection.close();
        System.out.println("发送消息结束");
    }
(3)消息消费者(监听、堵塞和限制时间)编码
public class JmsComsumer {
    public static final String ACTIVEMQ_URL="tcp://localhost:61616";
    public static final String QUEUE_NMAE="queue";

    public static void main(String[] args) throws JMSException, IOException {
        //1、创建连接工厂,采用默认的用户名和密码
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
        //2、通过创建工厂,获得连接connection并启动访问
        Connection connection = activeMQConnectionFactory.createConnection();
        connection.start();
        //3、创建会话session,里面有两个参数:事务和签收
        Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
        //4、创建目的地(具体时间队列还是主题)
        Queue queue = session.createQueue(QUEUE_NMAE);
        //5、创建消费者
        MessageConsumer messageConsumer=session.createConsumer(queue);
//        while (true){
//            //与生产者的消息类型一样,接收消息receive(),限制时间接收消息
//            TextMessage textMessage=(TextMessage) messageConsumer.receive(4000L);
//            if(null!=textMessage){
//                System.out.println("消费者接受到的消息:"+textMessage.getText());
//            }else {
//                break;
//            }
//        }

        //5、通过监听器的方式来接收消息
        messageConsumer.setMessageListener((message)->{

                if(null!=message && message instanceof TextMessage){
                    TextMessage textMessage=(TextMessage) message;
                    try {
                        System.out.println("消费者接受到的消息:"+textMessage.getText());
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
                    try {
                        textMessage.acknowledge();
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }

                }

        });
        //保证控制台不灭
        System.in.read();
        messageConsumer.close();
        session.close();
        connection.close();
    }
}

一个生产者多个消费者,采用轮询机制。

6、总结(JMS开发的基本步骤)
1)创建一个connection factory
2)通过connection factory来创建JMS connection
3)启动JMS connection
4)通过connection创建JMS session
5)创建JMS destaination(队列或主题)
6)创建JMS producer或JMS message并设置destaination(队列或主题)
7)创建JMS consumer或注册一个JMS message listener
8)发送或接收JMS message
9)关闭所有的资源
7、创建编码(topic)

​ 有时间限制,1:N关系,先起消费者再启动生产者

(1)发布主题生产者
public class JmsProducer {
    public static final String ACTIVEMQ_URL="tcp://localhost:61616";
    public static final String TOPIC_NMAE="topic";

    public static void main(String[] args) throws JMSException {
        //1、创建连接工厂,采用默认的用户名和密码
        ActiveMQConnectionFactory activeMQConnectionFactory=new ActiveMQConnectionFactory(ACTIVEMQ_URL);
        //2、通过创建工厂,获得连接connection并启动访问
        Connection connection=activeMQConnectionFactory.createConnection();
        connection.start();
        //3、创建会话session,里面有两个参数:事务和签收
        Session session=connection.createSession(true,Session.AUTO_ACKNOWLEDGE);
        //4、创建目的地(具体时间队列还是主题)
        Topic topic=session.createTopic(TOPIC_NMAE);
        //5、创建消息的生产者
        MessageProducer messageProducer=session.createProducer(topic);
        //6、通过使用messageProducer产生三条消息发送到mq的队列中
        for(int i=0;i<=3;i++){
            //7、创建消息(好比一个字符串2)
            TextMessage textMessage=session.createTextMessage("topic msg:"+i);
            //8、通过messageProducer发送给mq
            messageProducer.send(textMessage);
        }
        //9、关闭资源
        messageProducer.close();
        session.commit();
        session.close();
        connection.close();
        System.out.println("topic发送消息结束");
    }
}
(2)订阅消息的消费者
public class JmsComsumer {
    public static final String ACTIVEMQ_URL="tcp://localhost:61616";
    public static final String TOPIC_NMAE="topic";

    public static void main(String[] args) throws JMSException, IOException {
        //1、创建连接工厂,采用默认的用户名和密码
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
        //2、通过创建工厂,获得连接connection并启动访问
        Connection connection = activeMQConnectionFactory.createConnection();
        connection.start();
        //3、创建会话session,里面有两个参数:事务和签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //4、创建目的地(具体时间队列还是主题)
        Topic topic = session.createTopic(TOPIC_NMAE);
        //5、创建消费者
        MessageConsumer messageConsumer=session.createConsumer(topic);
        //通过监听器的方式来接收消息(拉姆达表达式)
        messageConsumer.setMessageListener((message)->{
            if(null!=message && message instanceof TextMessage){
                    TextMessage textMessage=(TextMessage) message;
                try {
                    System.out.println("消费者接受到的topic消息:"+textMessage.getText());
                } catch (JMSException e) {
                    e.printStackTrace();
                }

            }
        });
        //保证控制台不灭
        System.in.read();
        messageConsumer.close();
        session.close();
        connection.close();
    }
}

生产者发布的所有消息,每个订阅者各自都拥有所有的消息。发送和接收的消息类型必须一致。

8、队列(queue)和主题(Topic)的区别
比较项目Topicqueue
工作模式订阅-发布模式负载均衡模式(点对点模式)
状态无状态队列数据默认会在mq服务器上以文件形式保存
传递完整性若无订阅者,消息会被丢弃消息不会丢弃
处理效率会随订阅者增加而明显降低一条消息对应一个消费者
数量一对多一对一
先启动消费者在启动生产者先启动生产者在启动消费者
9、消息的可靠性
  • 持久化(PERSISTENT):服务器宕机,消息依然存在

    messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT)
    
  • 事务:将创建会话session的第一个参数为true,则在关闭session之前必须session.commit();为false是自动提交。使用事务时,加强容错,commit避免消息的重复消费。

    Session session=connection.createSession(true,Session.AUTO_ACKNOWLEDGE);
    //session.commit();
    //session.close();
    
    try{//没问题直接提交
         session.commit();
    }catch (Exception e){//报异常,回滚
           session.rollback();
     }finally {
           if(null!=session){//关闭session
                session.close();
            }
      }
    
  • 签收(acknowledge):消费者端将创建会话session的第二个参数就是签收,分为:自动(Session.AUTO_ACKNOWLEDGE)、手动(Session.CLIENT_ACKNOWLEDGE)和可允许重复签收(Session.DUPS_OK_ACKNOWLEDGE)。经常使用自动和手动,避免在消费者消息的重复消费。若开事务之后,就不可以需要手动反馈消息。

    使用手动签收时,需要对消息作出反馈:

    //设置手动签收模式
    Session session=connection.createSession(true,Session.CLIENT_ACKNOWLEDGE); 
    TextMessage textMessage=(TextMessage) message;
     System.out.println("消费者接受到的消息:"+textMessage.getText());
    //手动反馈消息 
    textMessage.acknowledge();
    

    事务和签收的关系:

    ​ (1)在事务性会话中,当一个事物被成功提交则消息被自动签收,如果事务回滚,则消息会被再次传送。

    ​ (2)非事务性会话中,消息合适被确认取决于创建绘画室的应答模式(acknowledgement mode)。

10、创建持久化(Topic)编码
(1)发布者(publisher)
public class JmsProducer {
    public static final String ACTIVEMQ_URL="tcp://localhost:61616";
    public static final String TOPIC_NMAE="topic";

    public static void main(String[] args) throws JMSException {
        //1、创建连接工厂,采用默认的用户名和密码
        ActiveMQConnectionFactory activeMQConnectionFactory=new ActiveMQConnectionFactory(ACTIVEMQ_URL);
        //2、通过创建工厂,获得连接connection并启动访问
        Connection connection=activeMQConnectionFactory.createConnection();
//        connection.start();
        //3、创建会话session,里面有两个参数:事务和签收
        Session session=connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
        //4、创建目的地(具体时间队列还是主题)
        Topic topic=session.createTopic(TOPIC_NMAE);
        //5、创建消息的生产者
        MessageProducer messageProducer=session.createProducer(topic);
        //消息持久化
        messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);
        //启动
        connection.start();
        //6、通过使用messageProducer产生三条消息发送到mq的队列中
        for(int i=0;i<=3;i++){
            //7、创建消息(好比一个字符串2)
            TextMessage textMessage=session.createTextMessage("topic msg:"+i);
            //8、通过messageProducer发送给mq
            messageProducer.send(textMessage);
        }
        //9、关闭资源
        messageProducer.close();
        session.close();
        connection.close();
        System.out.println("topic发送消息结束");
    }
}

(2)订阅者(subscriber)
public class JmsComsumer {
    public static final String ACTIVEMQ_URL="tcp://localhost:61616";
    public static final String TOPIC_NMAE="queue";

    public static void main(String[] args) throws JMSException, IOException {
        //1、创建连接工厂,采用默认的用户名和密码
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
        //2、通过创建工厂,获得连接connection并启动访问
        Connection connection = activeMQConnectionFactory.createConnection();
        //connection.start();
        connection.setClientID("张三");
        //3、创建会话session,里面有两个参数:事务和签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //4、创建目的地(具体时间队列还是主题)
        Topic topic = session.createTopic(TOPIC_NMAE);
        //发布订阅模式
        TopicSubscriber topicSubscriber=session.createDurableSubscriber(topic,"remark");
        //启动
        connection.start();
        //5、创建消息的接收
        Message message=topicSubscriber.receive();
        while (null!=message){
            TextMessage textMessage=(TextMessage) message;
            System.out.println("消费者接受到的topic消息:"+textMessage.getText());
            message=topicSubscriber.receive(5000L);
        }

        session.close();
        connection.close();
    }
}

持久化Topic总结:一定要先运行消费者,类似于向MQ注册,再运行生产者去发送消息,这样在消费者都会接收到生产者发送的消息,若消费者离线,重启之后也会接收到生产者发送的消息。

11、ActiveMQ的broker

​ 相当于一个ActiveMQ的实例。简单来说就是实现了用代码的形式启动ActiveMQ将MQ嵌入到java代码中,以便随时能够启动。

实现:

1、配置activeMQ.xml

命令:./activemq start xbean:file:/myactiveMQ/apache-activemq-5.15.9/config/activemq02.xml

2、导入依赖

 <dependency>
     <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
       <version>2.9.5</version>
   </dependency>

3、代码实现

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

12、Spring整合ActiveMQ
  • pom.xml的maven依赖(最重要的两个包)

            <!--spring整合activemq-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jms</artifactId>
                <version>4.3.23.RELEASE</version>
            </dependency>
            <!--activemq所需的pool-->
            <dependency>
                <groupId>org.apache.activemq</groupId>
                <artifactId>activemq-pool</artifactId>
                <version>5.15.9</version>
            </dependency>
    
    
  • 编写Spring配置文件applicationContext.xml

    <!--开启自动扫描的包-->
        <context:component-scan base-package="com.springboot.springbootactivemq.spring"></context:component-scan>
        <!--配置生产者-->
        <bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
            <property name="connectionFactory">
                <bean class="org.apache.activemq.ActiveMQConnectionFactory">
                    <property name="brokerURL" value="tcp://localhost:61616"></property>
                </bean>
            </property>
            <property name="maxConnections" value="100"></property>
        </bean>
        <!--目的地(queue还是topic)-->
        <!--queue-->
        <bean id="destinationQueue" class="org.apache.activemq.command.ActiveMQQueue">
            <constructor-arg index="0" value="spring-activemq-queue"></constructor-arg>
        </bean>
        <!--topic-->
        <bean id="destinationTopic" class="org.apache.activemq.command.ActiveMQTopic">
            <constructor-arg index="0" value="spring-activemq-queue"></constructor-arg>
        </bean>
        <!--jms工具类-->
        <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
             <property name="connectionFactory" ref="jmsFactory"></property>
              <!--监听队列-->
            <!--<property name="defaultDestination" ref="destinationQueue"/>-->
             <!--监听主题-->
            <property name="defaultDestination" ref="destinationTopic"/>
            <property name="messageConverter">
                <bean class="org.springframework.jms.support.converter.SimpleMessageConverter"/>
            </property>
        </bean>
    
        <!--監聽器-->
        <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
            <property name="connectionFactory" ref="jmsFactory"></property>
            <!--监听队列-->
            <!--<property name="destination" ref="destinationQueue"/>-->
             <!--监听主题-->
             <property name="destination" ref="destinationTopic"/>
            <property name="messageListener" ref="myMessageListener"></property>
        </bean>
    
    
  • 生产者

    /**
     * 监听器:不啟動消費者,通過監聽的方式
     */
    @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();
                }
    
            }
        }
    }
    
    
    /**
     * 生产者
     */
    @Service
    public class SpringMQ_Produce {
        @Autowired
        private JmsTemplate jmsTemplate;
        public static void main(String [] agrs){
            ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
            SpringMQ_Produce produce= (SpringMQ_Produce) applicationContext.getBean("springMQ_Produce");
    
            produce.jmsTemplate.send((session -> {
                TextMessage textMessage=session.createTextMessage("spring and activemq:");
                return textMessage;
            }));
            System.out.println("****send over*****");
        }
    }
    
    
  • 消费者

    /**
     * 消费者
     */
    @Service
    public class SpringMQ_consumer {
        @Autowired
        private JmsTemplate jmsTemplate;
        public static void main(String [] agrs) {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
            SpringMQ_consumer consumer = (SpringMQ_consumer) applicationContext.getBean("springMQ_consumer");
    
            String rec=(String) consumer.jmsTemplate.receiveAndConvert();
            System.out.println("****消費者接受的消息:"+rec);
        }
    
    }
    
    
13、SpringBoot整合ActiveMQ
  • pom.xml的maven依赖

    <!--springboot——>
    <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.2.RELEASE</version>
            <relativePath/>
        </parent>
    <!--springboot整合activemq-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-activemq</artifactId>
                <version>2.1.5.RELEASE</version>
            </dependency>
    
    
  • application.yml文件

    server:
      port: 99999   #端口号
    spring:
      application:
        name: springbootMQ-Queue   #项目名
      activemq:
        broker-url: tcp://localhost:61616   #ip
        user: admin     #用户名
        password: admin    #密码
      jms:
        pub--sub-domain: false    #false表示队列(queue)true表示主题(topic)
    
    
  • 生产者

    //配置类
    @Component
    @EnableJms
    public class ConfigBean {
        @Value("${spring.application.name}")   //application.yml里面的配置项目名
        private String myqueue;
    
        //队列
        @Bean
        public Queue queue(){
            return  new ActiveMQQueue(myqueue);
        }
    
        //topic主题
        @Bean
        public Topic topic(){
            return  new ActiveMQTopic(myqueue);
        }
    }
    
    
    //生产者类
    @Component
    public class SpringBootMQ_Produce {
        @Autowired
        private JmsMessagingTemplate jmsMessagingTemplate;
        @Autowired
        private Queue queue;
    
        //触发投送消息(test测试)
        public void produce(){
            jmsMessagingTemplate.convertAndSend(queue,"***"+ UUID.randomUUID().toString().substring( 0,6));
        }
    
        //每個3秒自动發送一個消息
        @Scheduled(fixedDelay = 3000)
        public void produceMsgScheduled(){
            jmsMessagingTemplate.convertAndSend(queue,"***"+ UUID.randomUUID().toString().substring( 0,6));
            System.out.println("****每個3秒發送一個消息****");
        }
    
    
    //程序入口
    @SpringBootApplication
    @EnableScheduling
    public class ActiveMQProduceApplication {
        public static void main(String[] args) {
            SpringApplication.run(ActiveMQProduceApplication.class, args);
        }
    
    }
    
    
  • 消费者

    @Component
    public class SpringBootMQ_Consumer {
        @JmsListener(destination = "${spring.application.name}")   //监听注解
        public void recevie(TextMessage textMessage){
            try {
                System.out.println("消费者接收到的消息:"+textMessage.getText());
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    }
    
    
14、ActiveMQ的协议(NIO或auto+nio)

​ 默认使用TCP协议,具有性能好、稳定性强;使用字节流方式传递,效率高;跨平台。NIO提高的性能比TCP更好。

​ NIO和NIO+auto协议的配置分别在安装目录下activemq.xml中添加:<transportConnector name="nio" uri="nio://0.0.0.0:61618?trace=true"/><transportConnector name="auto+nio" uri="auto+nio://0.0.0.0:61618maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

15、ActiveMQ的持久化机制
(1)AMQ

​ 基于文件的存储方式,文件默认大小为32M,适用于activeMQ 5.3之前的版本,已过时。

(2)KahaDB(activeMQ5.4之后默认使用)

​ 是目前默认的存储方式,可适用于任何场景,提高性能和恢复力,消息存储使用一个事务日志(db-number.log)和一个索引文件(db.data)来存储它所有的地址,是一个专门针对消息持久化的解决方案,对典型的消息使用模式进行了优化。数据被加载到data log中,当不再需要log文件是,log文件会被丢弃(删除或归档)。http://activemq.apache.org/persistence.html

(3)JDBC 消息存储

对于长时间的存储,推荐使用JDBC,使用持久化messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);步骤如下:

  • 下载mysql驱动包,放到activemq安装目录的lib文件夹下;

  • 修改activemq下config的active.xml文件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gFrK0U0C-1600420512324)(C:\Users\jha04\AppData\Roaming\Typora\typora-user-images\1599199349178.png)]

  • 重新启动active。成功之后,数据库自动创建三张表。

    ACTIVEMQ_MSGS:消息表,queue和topic都存储在里面,消费之后,消息会被删除,表中各字段的意思如下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZqVOxRFc-1600420512328)(C:\Users\jha04\AppData\Roaming\Typora\typora-user-images\1599200035453.png)]

    ACTIVEMQ_ACKS:存储持久订阅的信息和最后一个持久订阅接收的信息ID ,表中各字段的意思如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9z5X3UOW-1600420512329)(C:\Users\jha04\AppData\Roaming\Typora\typora-user-images\1599199957299.png)]

​ ACTIVEMQ _LOCK:在集群环境中才有用,只有一个Broker可以获得消息,称为Master Broker,其他的只能作为备份等待MAster Broker怒可用,才可能成为下一个Master Broker。用于记录·哪个Broker是当前的Master Broker。

(4) 带高速缓存的JDBC Journal

​ 带高速缓存的日志消息存储,提高了性能,当消费者的消息速度能够及时跟上生产者消息的生产速度时,journal文件能够大大减少需要写入到DB中的消息。修改如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a0tXtFlx-1600420512331)(C:\Users\jha04\AppData\Roaming\Typora\typora-user-images\1599202422028.png)]

(5)LevelDB

​ 基于文件的本地数据库存储

16、ActiveMQ的高级特性
(1)异步投递

​ 默认消息是使用异步发送方式,除非明确指定使用同步发送的方式或者在未使用事务的前提下发送持久化的消息,这两种情况都是同步发送。开启异步投递是,需要设置回调函数

//开启异步投递,在允许失败的情况下有少量的数据丢失,
(ActiveMQConnectionFactory )activeMQConnectionFactory.setAlwaysSyncSend(true);

String msgID = message.getJMSMessageID();
 //异步投递的回调方法
  messageProducer.send(message, new AsyncCallback() {
    @Override
    public void onException(JMSException e) {
       System.out.println(msgID+"false");
     }
     @Override
      public void onSuccess() {
        System.out.println(msgID+"ok");
      }
   });

(2)延时投递和定时投递

​ 修改active.xml文件在broker中加上schedulerSupport=“true”;

​ java代码的修改

//延时3s
message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY,delay);
//间隔4s
message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD,period);
//重复5次
message.setIntProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT,repeat);

(3)消息重试机制

​ 什么情况会发生消息重试机制:

  • 客户端使用了事务切在session中调用了rollback();
  • 客户端使用了事务切在调用commit()之前关闭了session()或没有commit();
  • 客户端在lCLIENT_ACKNOWLEDGE的签收模式下,session()调用了recover()。

以上情况会导致消息重试机制,默认每1秒钟重发6次。

修改系统默认的消息重发机制如下:

//自定义重发机制
RedeliveryPolicy redeliveryPolicy=new RedeliveryPolicy() redeliveryPolicy.setMaximumRedeliveries(3);
activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);

重发机制的属性说明:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H3M8Lodz-1600420512333)(C:\Users\jha04\AppData\Roaming\Typora\typora-user-images\1599468196965.png)]

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值