ActiveMQ进阶4---ActiveMQ高级特性

11、高级特性

11.1、异步投递

(1)什么是异步投递

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WOtpaSim-1605321072596)(D:%5C%E6%96%87%E6%A1%A3%5CActiveMQ%E5%AD%A6%E4%B9%A0%E6%96%87%E6%A1%A3%5Cimages05%5Cimage-20201113205404123.png)]

总结:

① 异步发送可以让生产者发的更快。

② 如果异步投递不需要保证消息是否发送成功,发送者的效率会有所提高。如果异步投递还需要保证消息是否成功发送,并采用了回调的方式,发送者的效率提高不多,这种就有些鸡肋。

(2)三种方式

// 方式1
private static final String ACTIVEMQ_URL = "tcp://118.24.20.3:61626?jms.useAsyncSend=true";
// 方式2
activeMQConnectionFactory.setUseAsyncSend(true);
// 方式3
((ActiveMQConnection)connection).setUseAsyncSend(true);

(3)异步发送如何确认发送成功

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8yf0nxK1-1605321072599)(D:%5C%E6%96%87%E6%A1%A3%5CActiveMQ%E5%AD%A6%E4%B9%A0%E6%96%87%E6%A1%A3%5Cimages05%5Cimage-20201113205812121.png)]

异步发送的回调

activeMQConnectionFactory.setUseAsyncSend(true);   // 设置异步发送
ActiveMQMessageProducer messageProducer = (ActiveMQMessageProducer) session.createProducer(queue);
try {
    
    
    for (int i = 0; i < 3; i++) {
    
    
        TextMessage textMessage = session.createTextMessage("QUEUQ---第" + i + "条message!");
        textMessage.setJMSMessageID(UUID.randomUUID().toString());
        final String msgID = textMessage.getJMSMessageID();
        messageProducer.send(textMessage, new AsyncCallback() {
    
     // 重载的send方法
            @Override
            public void onSuccess() {
    
    
                System.out.println("发送成功的消息ID:" + msgID);
            }

            @Override
            public void onException(JMSException e) {
    
    
                System.out.println("发送失败的消息ID:" + msgID);
            }
        });

    }
    System.out.println("消息发送完成!");
} catch (Exception e) {
    
    
    e.printStackTrace();
} finally {
    
    
    activeMQConnectionFactory.close();
    session.close();
    connection.close();
}

11.2、延迟投递和定时投递

(1)介绍

可以设置的具体延时和定时参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SivYytUJ-1605321072600)(D:%5C%E6%96%87%E6%A1%A3%5CActiveMQ%E5%AD%A6%E4%B9%A0%E6%96%87%E6%A1%A3%5Cimages05%5Cimage-20201113211813644.png)]

具体见官网文档:http://activemq.apache.org/delay-and-schedule-message-delivery.html

(2)修改配置文件

<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}"  schedulerSupport="true" >

(3)代码实现

生产者

public class JmsProduce_delay {
    
    
    private static final String ACTIVEMQ_URL = "tcp://192.168.5.130:61608";
    private static final String ACTIVEMQ_QUEUE_NAME = "Schedule01";

    public static void main(String[] args) throws JMSException {
    
    
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
        Connection connection = activeMQConnectionFactory.createConnection();
        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Queue queue = session.createQueue(ACTIVEMQ_QUEUE_NAME);
        MessageProducer messageProducer = session.createProducer(queue);
        long delay =  10*1000;
        long period = 5*1000;
        int repeat = 3 ;
        try {
    
    
            for (int i = 0; i < 3; i++) {
    
    
                TextMessage textMessage = session.createTextMessage("tx msg--" + i);
                // 延迟的时间
                textMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay);
                // 重复投递的时间间隔
                textMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, period);
                // 重复投递的次数
                textMessage.setIntProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT, repeat);
                // 此处的意思:该条消息,等待10秒,之后每5秒发送一次,重复发送3次。
                messageProducer.send(textMessage);
            }
            System.out.println("消息发送完成");
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            messageProducer.close();
            session.close();
            connection.close();
        }
    }
}

消费者

public class JmsConsumer {
    
    
    private static final String ACTIVEMQ_URL = "tcp://192.168.5.130:61608";
    private static final String ACTIVEMQ_QUEUE_NAME = "Schedule01";

    public static void main(String[] args) throws JMSException, IOException {
    
    
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
        Connection connection = activeMQConnectionFactory.createConnection();
        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Queue queue = session.createQueue(ACTIVEMQ_QUEUE_NAME);
        MessageConsumer messageConsumer = session.createConsumer(queue);
        messageConsumer.setMessageListener(new MessageListener() {
    
    

            public void onMessage(Message message) {
    
    
                if (message instanceof TextMessage) {
    
    
                    try {
    
    
                        TextMessage textMessage = (TextMessage) message;
                        System.out.println("***消费者接收到的消息:   " + textMessage.getText());
                        textMessage.acknowledge();
                    } catch (Exception e) {
    
    
                        System.out.println("出现异常,消费失败,放弃消费");
                    }
                }
            }
        });
        System.in.read();
        messageConsumer.close();
        session.close();
        connection.close();
    }
}

11.3、消息消费的重试机制

(1)概念

消费者收到消息,之后出现异常了,没有告诉broker确认收到该消息,broker会尝试再将该消息发送给消费者。尝试n次,如果消费者还是没有确认收到该消息,那么该消息将被放到死信队列重,之后broker不会再将该消息发送给消费者。

(2)具体哪些情况会引发消息重发

① Client用了transactions且再session中调用了rollback

② Client用了transactions且再调用commit之前关闭或者没有commit

③ Client再CLIENT_ACKNOWLEDGE的传递模式下,session中调用了recover

(3)消息重发时间间隔和重发次数

间隔:1

次数:6

每秒发6次

(4) 有毒消息Poison ACK

一个消息被redelivedred超过默认的最大重发次数(默认6次)时,消费者会向MQ发一个“poison ack”表示这个消息有毒,告诉broker不要再发了。这个时候broker会把这个消息放到DLQ(私信队列)。

(5)属性说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FVfyOxwN-1605321072603)(D:%5C%E6%96%87%E6%A1%A3%5CActiveMQ%E5%AD%A6%E4%B9%A0%E6%96%87%E6%A1%A3%5Cimages05%5Cimage-20201113215155384.png)]

(6)代码验证

生产者发送3条数据

消费者。开启事务,却没有commit。重启消费者,前6次都能收到消息,到第7次,不会再收到消息。

public class Jms_TX_Consumer {
    
    
    private static final String ACTIVEMQ_URL = "tcp://192.168.5.130:61616";
    private static final String ACTIVEMQ_QUEUE_NAME = "dead01";

    public static void main(String[] args) throws JMSException, IOException {
    
    
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
        Connection connection = activeMQConnectionFactory.createConnection();
        connection.start();
        final Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
        Queue queue = session.createQueue(ACTIVEMQ_QUEUE_NAME);
        MessageConsumer messageConsumer = session.createConsumer(queue);
        messageConsumer.setMessageListener(new MessageListener() {
    
    
            public void onMessage(Message message) {
    
    
                if (message instanceof TextMessage) {
    
    
                    TextMessage textMessage = (TextMessage) message;
                    try {
    
    
                        System.out.println("***消费者接收到的消息:   " + textMessage.getText());
                        //session.commit();
                    }catch (Exception e){
    
    
                        e.printStackTrace();
                    }
                }
            }
        });
        //关闭资源
        System.in.read();
        messageConsumer.close();
        session.close();
        connection.close();
    }

activemq管理后台。多了一个名为ActiveMQ.DLQ队列,里面多了3条消息。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yIHqbgFQ-1605321072605)(D:%5C%E6%96%87%E6%A1%A3%5CActiveMQ%E5%AD%A6%E4%B9%A0%E6%96%87%E6%A1%A3%5Cimages05%5Cimage-20201113215414995.png)]

(7)修改默认参数

// 修改默认参数,设置消息消费重试3次
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
redeliveryPolicy.setMaximumRedeliveries(3);
activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);

(8)spring整合配置信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4fC6fBby-1605321072606)(D:%5C%E6%96%87%E6%A1%A3%5CActiveMQ%E5%AD%A6%E4%B9%A0%E6%96%87%E6%A1%A3%5Cimages05%5Cimage-20201113215727591.png)]

11.4、死信队列

(1)介绍

官网文档: http://activemq.apache.org/redelivery-policy

死信队列:异常消息规避处理的集合,主要处理失败的消息。

在这里插入图片描述
在这里插入图片描述

(2)死信队列的配置(一般采用默认)

  1. sharedDeadLetterStrategy:不管是queue还是topic,失败的消息都放到这个队列中。下面修改activemq.xml的配置,可以达到修改队列的名字。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FD3ioPSc-1605321072610)(D:%5C%E6%96%87%E6%A1%A3%5CActiveMQ%E5%AD%A6%E4%B9%A0%E6%96%87%E6%A1%A3%5Cimages05%5Cimage-20201113220550420.png)]

  2. individualDeadLetterStrategy:可以为queue和topic单独指定两个死信队列。还可以为某个话题,单独指定一个死信队列。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pkEljyTX-1605321072611)(D:%5C%E6%96%87%E6%A1%A3%5CActiveMQ%E5%AD%A6%E4%B9%A0%E6%96%87%E6%A1%A3%5Cimages05%5Cimage-20201113220629815.png)]

  3. 自动删除过期消息:过期消息是指生产者指定的过期时间,超过这个时间的消息。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mdb5EsqG-1605321072612)(D:%5C%E6%96%87%E6%A1%A3%5CActiveMQ%E5%AD%A6%E4%B9%A0%E6%96%87%E6%A1%A3%5Cimages05%5Cimage-20201113220716217.png)]

  4. 存放非持久消息到死信队列中

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eflLWIqJ-1605321072613)(D:%5C%E6%96%87%E6%A1%A3%5CActiveMQ%E5%AD%A6%E4%B9%A0%E6%96%87%E6%A1%A3%5Cimages05%5Cimage-20201113220745801.png)]

11.5、消息不被重复消费,幂等性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lOzsPm0j-1605321072614)(D:%5C%E6%96%87%E6%A1%A3%5CActiveMQ%E5%AD%A6%E4%B9%A0%E6%96%87%E6%A1%A3%5Cimages05%5Cimage-20201113221109526.png)]

猜你喜欢

转载自blog.csdn.net/qq_42372017/article/details/109687438
今日推荐