activemq预取与消息确认优化

prefecthSize
消费端预取消息数量,每次消费者获取到到消息数量小于等于prefecthSize,例如prefecthSize是10,每次消费者从broker拉取10条消息到本地内存。
在activemq中设置prefectSize如下,创建队列时配置。

Destination destination=session.createQueue("gqueue?consumer.prefetchSize=10");

通过设置prefecthSize,按照实际需求平衡预取消息数量,当然这样还达不到优化到目的,还需要配合optimizeAcknowledge(开启批量消息确认优化)来达到提高消息处理效率。

optimizeAcknowledge
optimizeAcknowledge到设置方式如下,消费者创建时配置。

ConnectionFactory connectionFactory= new ActiveMQConnectionFactory ("tcp://192.168.0.15:61616?jms.optimizeAcknowledge=true&jms.optimizeAcknowledgeTimeOut=10000");

优化回传默认阀值是0.65*prefecthSize,当pendingAck消息堆积到达阀值,消息会一次性批量进行ack。
optimizeAcknowledgeTimeOut表示最迟ack时间长度,到达时间限制没有达到阀值也会进行批量ack回传。

如何提高消息消费速率?
为了达到提高消费者消费消息速率,可以设置prefecthSize为一个比较大的值,这个值时消费者的消费能力之内的;并且消费者开启optimizeAcknowledge,进行批量回传优化,此时获取消息和ack都是批量操作,能够减少网络开销,从而提高消费者消息消费速率。

需要注意什么?
需要注意的是,prefecthSize的配置需要结合实际的消费者消费能力。假如配置过大,某个消费者一次性拉取的大量的消息,但是却无法及时完成处理,这会导致其他消费者干等待,而拉取大量消息的消费者却一直在忙活;假如配置过小,就达不到我们理想的优化效率,因此这个值怎么设置,需要实际生产中去调试。

下面进行简单例子来进行测试
设置prefecthSize为50的一个生产者,连续发送100条消息到broker,代码如下。

public class JMSCommonLoopProducer {
    public static void main(String[] args) throws JMSException {
        //根据broker URL建立连接工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.0.15:61616");
        //创建连接
        Connection connection = connectionFactory.createConnection();
        connection.start();
        //创建会话
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建队列(有则不创建)
        Destination destination = session.createQueue("garine-queue?consumer.prefetchSize=10");
        //创建生产者
        MessageProducer producer = session.createProducer(destination);
        for (int i =0;i< 100;i++){
            //创建文本消息,有多种消息类型
            TextMessage textMessage = session.createTextMessage("Hello garine" + "-" +i);
            //发送消息
            producer.send(textMessage);
        }
        System.out.println("over");
        session.close();
    }
}

然后是启动两个消费者,消费者同时开启了优化回传。

public class JMSSessionPrefecthConsumer {
    public static void main(String[] args) throws JMSException, InterruptedException {
        //根据broker URL建立连接工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.0.15:61616?jms.optimizeAcknowledge=true&jms.optimizeAcknowledgeTimeOut=100000");
        //创建连接
        Connection connection = connectionFactory.createConnection();
        connection.start();
        //创建会话
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建队列(有则不创建)
        Destination destination = session.createQueue("garine-queue?consumer.prefetchSize=10");
        //创建生产者
        MessageConsumer consumer = session.createConsumer(destination);
        //接受文本消息,阻塞等待
        for (int i=1;i<=100;i++){
            TextMessage textMessage = (TextMessage) consumer.receive();
            System.out.println(textMessage.getText());
            Thread.sleep(2000);
        }
        session.close();
    }
}

两个消费者执行结果如下:
消费者1
这里写图片描述

消费者2
这里写图片描述

可以看出每次消费者获取消息都是批量获取的,例如消费者1第一次获取10条消息到本地内存(unconsumeMessage列表),那么就不会分派给消费者2。消费者2就从第11条开始获取消息,同样也是批量获取,交替获取。

同时还需要注意,这里还开起的优化回传,通过activemq控制台可以看到,每次Number Of Pending Messages被确认时都是7条一起确认的,0.65*10 = 6.5 取整数刚好七条一起回传。

试着把jms.optimizeAcknowledgeTimeOut=5000作为消费配置,发现每次确认消息变成3条,也就是说这个时间限制是起作用的,超过时间限制还达不到阀值的时候就会发起一次批量ack,这里面阀值是7,但是超过5000ms还没到达阀值,因此3条消息也要进行回传。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值