ActiveMQ性能優化

ActiveMq運行是比較穩定的,數據的吞吐速度也很高,如果出現入隊列或者出隊列慢的問題,先檢查一下自己的代碼,是不是本身取到數據後處理過慢。

本文的關於性能優化,其實是列舉出一些需要注意的點,請確保你的項目沒有一下問題:

1. 使用spring的JmsTemplate

JmsTemplate的send和convertAndSend會使用持久化mode,即使你設置了NON_PERSISTENT。這會導致入隊列速度變得非常慢。

解決辦法,使用下面的MyJmsTemplate代替JmsTemplate。

publicclassMyJmsTemplateextendsJmsTemplate {private Session session;

public MyJmsTemplate() {
super();
}

public MyJmsTemplate(ConnectionFactory connectionFactory) {
super(connectionFactory);
}

publicvoid doSend(MessageProducer producer, Message message) throws JMSException {
if (isExplicitQosEnabled()) {
producer.send(message, getDeliveryMode(), getPriority(), getTimeToLive());
} else {
producer.send(message);
}
}

public Session getSession() {
return session;
}

publicvoid setSession(Session session) {
this.session = session;
}
}

2. DeliveryMode的選擇,如果你入隊列的數據,不考慮MQ掛掉的情況(這概率很小),使用NON_PERSISTENT會顯著提高數據寫入速度。

3. 生產者使用事物會提高入隊列性能,但是消費者如果啓動了事物則會顯著影響數據的消費速度。相關代碼如下:

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

代碼中的false代表不啓動事物。

4. 消費者的消息處理即onMessage方法優化,舉例如下:

publicclassSmsMoPoolimplementsMessageListener {privatefinalstatic Logger logger = LoggerFactory.getLogger(SmsMoPool.class);
private DefaultEventPubliser moEventPublisher;
privatefinal EventFactory eventFactory = new DefaultEventFactory();
private DefaultDataGather dataGather;
private ExecutorService pool = Executors.newFixedThreadPool(5);

@Overridepublicvoid onMessage(final Message message) {
pool.execute(new Runnable() {
@Overridepublicvoid run() {
final ObjectMessage msg = (ObjectMessage) message;
Serializable obj = null;
try {
obj = msg.getObject();
} catch (JMSException e) {
logger.error("從消息隊列獲得上行信息異常{}", e);
}
if (obj != null) {
dataGather.incrementDateCount(MasEntityConstants.TRAFFIC_SMS_MO_IN);
AgentToServerReq req = (AgentToServerReq) obj;
if (logger.isInfoEnabled()) {
logger.info("驅動-->調度:{}", req.toXmlStr());
}
Event event = eventFactory.createMoEvent(req);
moEventPublisher.publishEvent(event);
}
}
});
}
}

這段代碼使用了線程池,另一點要注意的是msg.getObject();這個方法是一個比較耗時的方法,你的代碼中不應該出現多次getObject()。

5. 消費者使用預取,如何使用預取,下面以spring版本爲例

<beanclass="org.apache.activemq.command.ActiveMQQueue"><constructor-argvalue="data.mo?consumer.prefetchSize=100"/></bean>

預取數量根據具體入隊列數據而定,以上設置100,是針對2000/sec入隊列速度設定的。 另外如果是慢消費者,這裏可設置爲1。

6. 檢查你的MQ數據吞吐速度,保持生產和消費的平衡,不會出現大量積壓。

7. ActiveMQ使用TCP協議時 tcpNoDelay=默認是false ,設置爲true可以提高性能。

還是spring版本的:

<beanid="mqPoolConnectionFactory"class="org.apache.activemq.pool.PooledConnectionFactory"destroy-method="stop"><propertyname="connectionFactory"><beanid="mqConnectionFactory"class="org.apache.activemq.ActiveMQConnectionFactory"p:useAsyncSend="true"p:brokerURL="failover://(tcp://127.0.0.1:61616?tcpNoDelay=true)"/></property></bean>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章