1. 優化ActiveMQ性能
1.1. 一般技術
1.1.1. Persistent vs Non-Persistent Message
持久化和非持久化傳遞
1.PERSISTENT(持久性消息)
這是 ActiveMQ 的默認傳送模式,此模式保證這些消息只被傳送一次和成功使用一次。對於這些消息,可靠性是優先考慮的因素。可靠性的另一個重要方面是確保持久性消息傳送至目標後,消息服務在向消費者傳送它們之前不會丟失這些消息。這意味着在持久性消息傳送至目標時,消息服務將其放入持久性數據存儲。如果消息服務由於某種原因導致失敗,它可以恢復此消息並將此消息傳送至相應的消費者。雖然這樣增加了消息傳送的開銷,但卻增加了可靠性。
2.NON_PERSISTENT(非持久性消息)
保證這些消息最多被傳送一次。對於這些消息,可靠性並非主要的考慮因素。
此模式並不要求持久性的數據存儲,也不保證消息服務由於某種原因導致失敗後消息不會丟失。
有兩種方法指定傳送模式:
1.使用setDeliveryMode 方法,這樣所有的消息都採用此傳送模式;
2.使用send 方法爲每一條消息設置傳送模式;
方法一:void send(Destination destination, Message message, int deliveryMode, int priority,long timeToLive);
方法二:void send(Message message, int deliveryMode, int priority, longtimeToLive);
其中 deliveryMode 爲傳送模式,priority 爲消息優先級,timeToLive 爲消息過期
時間。
方法三:producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
JMS 規範1.1允許消息傳遞包括Persistent和Non-Persistent。
Non-persistent傳遞消息比Persistents傳遞消息速度更快,原因如下:
1) Non-persistent發送消息是異步的,Producer不需要等待Consumer的receipt消息。如下圖:
2) Persisting 傳遞消息是需要把消息存儲起來。然後在傳遞,這樣很慢 。
1.1.2. Transactions
事務
以下列子說明了Transaction比Non-transaction的性能高。
Transaction和Non-transaction代碼如下:
1.1.3. 超快回應消息
內嵌 broker;如下圖:
下面以Co-lcate (合作定位)with a broker爲例。
其運行原理如下圖:
Java代碼如下:
創建一個queue服務:
創建一個queueRequestor:
注意:
設置發送的消息不需要copy。
1.1.4. Tuning the OpenWire protocol
跨語言協議
//TODO
1.1.5. Tuning the TCP Transport
TCP協議是ActiveMQ使用最常見的協議。
有以下兩點影響TCP協議性能:
1) socketBufferSize=緩存,默認是65536。
2) tcpNoDelay=默認是false,
示例如下:
1.2. 優化消息發送
1.2.1. Asynchronous Send
在ActiveMQ4.0以上,所有的異步或同步對於Consumer來說是變得可配置了。
默認是在ConnectionFactory、Connection、Connection URI等方面配置對於一個基於Destination 的Consumer來說。
衆所周之,如果你想傳遞給Slow Consumer那麼你可能使用異步的消息傳遞,但是對於Fast Consumer你可能使用同步發送消息。(這樣可以避免同步和上下文切換額外的增加Queue堵塞花費。如果對於一個Slow Consumer,你使用同步發送消息可能出現Producer堵塞等顯現。
ActiveMQ默認設置dispatcheAsync=true是最好的性能設置。如果你處理的是Slow Consumer則使用dispatcheAsync=true,反之,那你使用的是Fast Consumer則使用dispatcheAsync=false。
用Connection URI來配置Async如下:
ActiveMQConnectionFactory("tcp://locahost:61616?jms.useAsyncSend=true");用ConnectionFactory配置Async如下:
((ActiveMQConnectionFactory)connectionFactory).setUseAsyncSend(true);用Connection配置Async如下:
((ActiveMQConnection)connection).setUseAsyncSend(true);
1.2.2. Producer Flow Control
這種適合於慢的消費者,大量的消息暫時存儲到內存中,然後慢慢的dispatche。
運行原理如圖下:
Java代碼如下:
Xml配置的策略如下:
Disabled Producer Flow Control運行原理:
1.3. 優化消息消費者
消息消費的內部流程結構如下:
1.3.1. Prefetch Limit
ActiveMQ默認的prefetch大小不同的:
Queue Consumer 默認大小=1000
Queue Browser Consumer默認大小=500
Persistent Topic Consumer默認大小=100
Non-persistent Topic Consumer默認大小=32766
Prefecth policy設置如下:
設置prefetch policy在 Destinations上:
1.3.2. Delivery and Acknowledgement of messages
傳遞和回執消息。
建議使用Session.DUPS_ACKNOWLEDGE。
JMS消息只有在被確認之後,才認爲已經被成功地消費了。消息的成功消費通常包含三個階段:客戶接收消息、客戶處理消息和消息被確認。
在事務性會話中,當一個事務被提交的時候,確認自動發生。在非事務性會話中,消息何時被確認取決於創建會話時的應答模式(acknowledgement mode)。該參數有以下三個可選值:
Session.AUTO_ACKNOWLEDGE。當客戶成功的從receive方法返回的時候,或者從MessageListener.onMessage方法成功返回的時候,會話自動確認客戶收到的消息。
Sessiion.TRANSACTION。用session.commit()回執確認。
Session.CLIENT_ACKNOWLEDGE。客戶通過消息的acknowledge方法確認消息。需要注意的是,在這種模式中,確認是在會話層上進行:確認一個被消費的消息將自動確認所有已被會話消費的消息。例如,如果一個消息消費者消費了10個消息,然後確認第5個消息,那麼所有10個消息都被確認。
Session.DUPS_ACKNOWLEDGE。該選擇只是會話遲鈍第確認消息的提交。當消息到達一定數量後,纔開始消費該消息。如果JMS provider失敗,那麼可能會導致一些重複的消息。如果是重複的消息,那麼JMS provider必須把消息頭的JMSRedelivered字段設置爲true。
優化回執:
1.3.3. Slow Consumer Handling
慢消費者綁定策略
Slow Consumer將一起一個問題,對於非持久主題上,強迫Broker發送的消息堆積起來,使得Broker對於Producer發送慢了下來,同時Fast Consumer也慢了下來。
目前,我們有一個策略來配置在原有Consumer的預存的大小的基礎上增加了一定的緩存大小。因此,這個大小最終一旦滿了,則舊消息將會丟棄,新消息則會進入。這將保持了一定的緩存大小。
Pending Message Limit Strategy
等待消息限制策略
對於Slow Consumer來說,你將配置PendingMessageLimitStrategy策略來處理不同的策略。
以下有兩種實現的策略:
ConstantPendingMessageLimitStrategy
Limit可以設置0、>0、-1三種方式:
0表示:不額外的增加其預存大小。
>0表示:在額外的增加其預存大小。
-1表示:不增加預存也不丟棄舊的消息。
<constantPendingMessageLimitStrategy limit="50"/>PrefetchRatePendingMessageLimitStrategy
這種策略是利用Consumer的之前的預存的大小乘以其倍數等於現在的預存大小。
<prefetchRatePendingMessageLimitStrategy multiplier="2.5"/>Configuring the Eviction Policy
配置去除策略
ActiveMQ有兩種方式,默認配置方式如下:
<oldestMessageEvictionStrategy/>
方式二:
去除舊消息根據它的優先級來判斷,如果你有一個較高的優先級的舊消息,則去除低優先級的消息。
<oldestMessageWithLowestPriorityEvictionStrategy/> 1.3.4. Destination Options
Destination Options 這種方式提供了擴展了JMS Consumer但並不是擴展了JMS API。以URL的形式來編碼的。
Consumer Options
示例如下:
queue = new ActiveMQQueue("TEST.QUEUE?consumer.dispatchAsync=false&consumer.prefetchSize=10");
consumer = session.createConsumer(queue);