ActiveMQ性能优化笔记

以前都是看看消息队列的文章,程序里简单的调用一下接口,一直没有详细的搭建,并不了解其中的细节。导致最近项目上使用ActiveMQ,踩到了性能的坑,在网上找各种资料,这里简单记录一下。

队列的类型

由于我使用的是P2P的队列方式,TOPIC类型的没有使用,所以这里只是关于点对点的记述

环境搭建

这个网上的教程很多,找一篇,照着弄就可以了。我这里的环境是简单的一个单点的服务,并没有集群。

踩到的坑

  1. 生产者生产消息很快,但是入队的速度却很慢。
  2. 消费者消费速度也是很慢。

消息入队的性能

消息持久化

由于activeMQ默认是开启消息持久化的,在消息入队以后会把消息持久化到本地数据库里,这个会很大程度的影响入队性能。不过,对消息持久化有要求的功能,还是不能关闭这个配置。

同步/异步发送消息

producer发送消息有同步和异步两种模式,可以通过配置文件和代码配置:

  • broker-url: nio://192.168.0.54:61616?jms.useAsyncSend=true
  • ((ActiveMQConnection)connection).setUseAsyncSend(true);
acitveMQ服务器通信方式

apache-activemq-5.9.0\conf\activemq.xml中有如下配置:

<transportConnectors>
            <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
            <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
</transportConnectors>

这里配置了各种协议,可以增加或修改协议为nio模式。

<transportConnector name="nio" uri="nio://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

这样消息入队的性能就有所提升。

消费者消费

这个更坑了,我采用默认模式,居然一秒就能处理百八十个消息,上网翻阅资料,才知道这里,客户端消费消息,有2种模式。

  1. 客户端拉取模式
  2. 服务端推送模式
optimizeACK

“可优化的ACK”,这是ActiveMQ对于consumer在消息消费时,对消息ACK的优化选项,也是consumer端最重要的优化参数之一,你可以通过如下方式开启:

  1. 在brokerUrl中增加如下查询字符串:

String brokerUrl = "tcp://localhost:61616?" + 

                   "jms.optimizeAcknowledge=true" + 

                   "&jms.optimizeAcknowledgeTimeOut=30000" + 

                   "&jms.redeliveryPolicy.maximumRedeliveries=6";

ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(brokerUrl);

我们需要在brokerUrl指定optimizeACK选项,其中brokerUrl参数选项是全局的,即当前factory下所有的connection/session/consumer都会默认使用这些值

  1. 在destinationUri中,增加如下查询字符串:

String queueName = "test-queue?customer.prefetchSize";

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

Destination queue = session.createQueue(queueName);

在destinationUri中指定prefetchSize(预获取)选项,也可以加在代码里

ActiveMQPrefetchPolicy prefetchPolicy = connectionFactory.getPrefetchPolicy();
prefetchPolicy.setQueuePrefetch(30);

optimizeAck表示是否开启“优化ACK”,只有在为true的情况下,prefetchSize(下文中将会简写成prefetch)以及optimizeAcknowledgeTimeout参数才会有意义。此处需要注意"optimizeAcknowledgeTimeout"选项只能在brokerUrl中配置。

如果prefetchACK为true,那么prefetch必须大于0;当prefetchACK为false时,你可以指定prefetch为0以及任意大小的正数。不过,当prefetch=0是,表示consumer将使用PULL(拉取)的方式从broker端获取消息,broker端将不会主动push消息给client端,直到client端发送PullCommand时;当prefetch>0时,就开启了broker push模式,此后只要当client端消费且ACK了一定的消息之后,会立即push给client端多条消息。

这就是所谓的拉取与推送模式。

当consumer端使用receive()方法同步获取消息时,prefetch可以为0和任意正值;当prefetch=0时,那么receive()方法将会首先发送一个PULL指令并阻塞,直到broker端返回消息为止,这也意味着消息只能逐个获取(类似于Request<->Response),这也是Activemq中PULL消息模式;当prefetch > 0时,broker端将会批量push给client 一定数量的消息(<= prefetch),client端会把这些消息(unconsumedMessage)放入到本地的队列中,只要此队列有消息,那么receive方法将会立即返回,当一定量的消息ACK之后,broker端会继续批量push消息给client端。

当consumer端使用MessageListener异步获取消息时,这就需要开发设定的prefetch值必须 >=1,即至少为1;在异步消费消息模式中,设定prefetch=0,是相悖的,也将获得一个Exception。

optimizeACK和prefetch配合,将会达成一个高效的消息消费模型:批量获取消息,并“延迟”确认(ACK)。prefetch表达了“批量获取”消息的语义,broker端主动的批量push多条消息给client端,总比client多次发送PULL指令然后broker返回一条消息的方式要优秀很多,它不仅减少了client端在获取消息时阻塞的次数和阻塞的时间,还能够大大的减少网络开支。optimizeACK表达了“延迟确认”的语义(ACK时机),client端在消费消息后暂且不发送ACK,而是把它缓存下来(pendingACK),等到这些消息的条数达到一定阀值时,只需要通过一个ACK指令把它们全部确认;这比对每条消息都逐个确认,在性能上要提高很多。由此可见,prefetch优化了消息传送的性能,optimizeACK优化了消息确认的性能。

如果消息很重要,特别是需要接收到”redelivery“的消息,那么我们需要将optimizeACK=false,prefetchSize=1

至此,只是简单的记述了使用的一些心得,还有很多具体的配置待了解。。。。。。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值