(2011-08-18 12:24:26)
標(biāo)簽:
雜談分類:
Java1. 優(yōu)化ActiveMQ性能
1.1. 一般技術(shù)
1.1.1. Persistent vs Non-Persistent Message
持久化和非持久化傳遞
1.PERSISTENT(持久性消息)
這是 ActiveMQ 的默認(rèn)傳送模式,此模式保證這些消息只被傳送一次和成功使用一次。對(duì)于這些消息,可靠性是優(yōu)先考慮的因素??煽啃缘牧硪粋€(gè)重要方面是確保持久性消息傳送至目標(biāo)后,消息服務(wù)在向消費(fèi)者傳送它們之前不會(huì)丟失這些消息。這意味著在持久性消息傳送至目標(biāo)時(shí),消息服務(wù)將其放入持久性數(shù)據(jù)存儲(chǔ)。如果消息服務(wù)由于某種原因?qū)е率。梢曰謴?fù)此消息并將此消息傳送至相應(yīng)的消費(fèi)者。雖然這樣增加了消息傳送的開銷,但卻增加了可靠性。
2.NON_PERSISTENT(非持久性消息)
保證這些消息最多被傳送一次。對(duì)于這些消息,可靠性并非主要的考慮因素。
此模式并不要求持久性的數(shù)據(jù)存儲(chǔ),也不保證消息服務(wù)由于某種原因?qū)е率『笙⒉粫?huì)丟失。
有兩種方法指定傳送模式:
1.使用setDeliveryMode 方法,這樣所有的消息都采用此傳送模式;
2.使用send 方法為每一條消息設(shè)置傳送模式;
方法一:void send(Destination destination, Message message, int deliveryMode, int priority,long timeToLive);
方法二:void send(Message message, int deliveryMode, int priority, longtimeToLive);
其中 deliveryMode 為傳送模式,priority 為消息優(yōu)先級(jí),timeToLive 為消息過期
時(shí)間。
方法三:producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
JMS 規(guī)范1.1允許消息傳遞包括Persistent和Non-Persistent。
Non-persistent傳遞消息比Persistents傳遞消息速度更快,原因如下:
1) Non-persistent發(fā)送消息是異步的,Producer不需要等待Consumer的receipt消息。如下圖:
2) Persisting 傳遞消息是需要把消息存儲(chǔ)起來。然后在傳遞,這樣很慢 。
1.1.2. Transactions
事務(wù)
以下列子說明了Transaction比Non-transaction的性能高。
Transaction和Non-transaction代碼如下:
1.1.3. 超快回應(yīng)消息
內(nèi)嵌 broker;如下圖:
下面以Co-lcate (合作定位)with a broker為例。
其運(yùn)行原理如下圖:
Java代碼如下:
創(chuàng)建一個(gè)queue服務(wù):
創(chuàng)建一個(gè)queueRequestor:
注意:
設(shè)置發(fā)送的消息不需要copy。
1.1.4. Tuning the OpenWire protocol
跨語言協(xié)議
//TODO
1.1.5. Tuning the TCP Transport
TCP協(xié)議是ActiveMQ使用最常見的協(xié)議。
有以下兩點(diǎn)影響TCP協(xié)議性能:
1) socketBufferSize=緩存,默認(rèn)是65536。
2) tcpNoDelay=默認(rèn)是false,
示例如下:
1.2. 優(yōu)化消息發(fā)送
1.2.1. Asynchronous Send
在ActiveMQ4.0以上,所有的異步或同步對(duì)于Consumer來說是變得可配置了。
默認(rèn)是在ConnectionFactory、Connection、Connection URI等方面配置對(duì)于一個(gè)基于Destination 的Consumer來說。
眾所周之,如果你想傳遞給Slow Consumer那么你可能使用異步的消息傳遞,但是對(duì)于Fast Consumer你可能使用同步發(fā)送消息。(這樣可以避免同步和上下文切換額外的增加Queue堵塞花費(fèi)。如果對(duì)于一個(gè)Slow Consumer,你使用同步發(fā)送消息可能出現(xiàn)Producer堵塞等顯現(xiàn)。
ActiveMQ默認(rèn)設(shè)置dispatcheAsync=true是最好的性能設(shè)置。如果你處理的是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
這種適合于慢的消費(fèi)者,大量的消息暫時(shí)存儲(chǔ)到內(nèi)存中,然后慢慢的dispatche。
運(yùn)行原理如圖下:
Java代碼如下:
Xml配置的策略如下:
Disabled Producer Flow Control運(yùn)行原理:
1.3. 優(yōu)化消息消費(fèi)者
消息消費(fèi)的內(nèi)部流程結(jié)構(gòu)如下:
1.3.1. Prefetch Limit
ActiveMQ默認(rèn)的prefetch大小不同的:
Queue Consumer 默認(rèn)大小=1000
Queue Browser Consumer默認(rèn)大小=500
Persistent Topic Consumer默認(rèn)大小=100
Non-persistent Topic Consumer默認(rèn)大小=32766
Prefecth policy設(shè)置如下:
設(shè)置prefetch policy在 Destinations上:
1.3.2. Delivery and Acknowledgement of messages
傳遞和回執(zhí)消息。
建議使用Session.DUPS_ACKNOWLEDGE。
JMS消息只有在被確認(rèn)之后,才認(rèn)為已經(jīng)被成功地消費(fèi)了。消息的成功消費(fèi)通常包含三個(gè)階段:客戶接收消息、客戶處理消息和消息被確認(rèn)。
在事務(wù)性會(huì)話中,當(dāng)一個(gè)事務(wù)被提交的時(shí)候,確認(rèn)自動(dòng)發(fā)生。在非事務(wù)性會(huì)話中,消息何時(shí)被確認(rèn)取決于創(chuàng)建會(huì)話時(shí)的應(yīng)答模式(acknowledgement mode)。該參數(shù)有以下三個(gè)可選值:
Session.AUTO_ACKNOWLEDGE。當(dāng)客戶成功的從receive方法返回的時(shí)候,或者從MessageListener.onMessage方法成功返回的時(shí)候,會(huì)話自動(dòng)確認(rèn)客戶收到的消息。
Sessiion.TRANSACTION。用session.commit()回執(zhí)確認(rèn)。
Session.CLIENT_ACKNOWLEDGE。客戶通過消息的acknowledge方法確認(rèn)消息。需要注意的是,在這種模式中,確認(rèn)是在會(huì)話層上進(jìn)行:確認(rèn)一個(gè)被消費(fèi)的消息將自動(dòng)確認(rèn)所有已被會(huì)話消費(fèi)的消息。例如,如果一個(gè)消息消費(fèi)者消費(fèi)了10個(gè)消息,然后確認(rèn)第5個(gè)消息,那么所有10個(gè)消息都被確認(rèn)。
Session.DUPS_ACKNOWLEDGE。該選擇只是會(huì)話遲鈍第確認(rèn)消息的提交。當(dāng)消息到達(dá)一定數(shù)量后,才開始消費(fèi)該消息。如果JMS provider失敗,那么可能會(huì)導(dǎo)致一些重復(fù)的消息。如果是重復(fù)的消息,那么JMS provider必須把消息頭的JMSRedelivered字段設(shè)置為true。
優(yōu)化回執(zhí):
1.3.3. Slow Consumer Handling
慢消費(fèi)者綁定策略
Slow Consumer將一起一個(gè)問題,對(duì)于非持久主題上,強(qiáng)迫Broker發(fā)送的消息堆積起來,使得Broker對(duì)于Producer發(fā)送慢了下來,同時(shí)Fast Consumer也慢了下來。
目前,我們有一個(gè)策略來配置在原有Consumer的預(yù)存的大小的基礎(chǔ)上增加了一定的緩存大小。因此,這個(gè)大小最終一旦滿了,則舊消息將會(huì)丟棄,新消息則會(huì)進(jìn)入。這將保持了一定的緩存大小。
Pending Message Limit Strategy
等待消息限制策略
對(duì)于Slow Consumer來說,你將配置PendingMessageLimitStrategy策略來處理不同的策略。
以下有兩種實(shí)現(xiàn)的策略:
ConstantPendingMessageLimitStrategy
Limit可以設(shè)置0、>0、-1三種方式:
0表示:不額外的增加其預(yù)存大小。
>0表示:在額外的增加其預(yù)存大小。
-1表示:不增加預(yù)存也不丟棄舊的消息。
<constantPendingMessageLimitStrategy limit="50"/>PrefetchRatePendingMessageLimitStrategy
這種策略是利用Consumer的之前的預(yù)存的大小乘以其倍數(shù)等于現(xiàn)在的預(yù)存大小。
<prefetchRatePendingMessageLimitStrategy multiplier="2.5"/>Configuring the Eviction Policy
配置去除策略
ActiveMQ有兩種方式,默認(rèn)配置方式如下:
<oldestMessageEvictionStrategy/>
方式二:
去除舊消息根據(jù)它的優(yōu)先級(jí)來判斷,如果你有一個(gè)較高的優(yōu)先級(jí)的舊消息,則去除低優(yōu)先級(jí)的消息。
<oldestMessageWithLowestPriorityEvictionStrategy/> 1.3.4. Destination Options
Destination Options 這種方式提供了擴(kuò)展了JMS Consumer但并不是擴(kuò)展了JMS API。以URL的形式來編碼的。
Consumer Options
Option Name
Default Value
Description
consumer.prefetchSize
variable
預(yù)設(shè)消息消費(fèi)者的消費(fèi)數(shù)量
consumer.maximumPendingMessageLimit
0
如果是慢消費(fèi)者則設(shè)置非持久主題最小的消息容量大小
consumer.noLocal
false
如果有一個(gè)相同的主題消費(fèi)者noLocal標(biāo)志是true。則表示它可以使用一個(gè)隊(duì)列。
consumer.dispatchAsync
false
用于異步發(fā)送消息
consumer.retroactive
false
設(shè)置一個(gè)恢復(fù)消費(fèi)者
consumer.selector
null
用于消費(fèi)者的消息選擇
consumer.exclusive
false
設(shè)置獨(dú)立消費(fèi)者
consumer.priority
0
配置消費(fèi)者的優(yōu)先級(jí)
示例如下:queue = newActiveMQQueue("TEST.QUEUE?consumer.dispatchAsync=false&consumer.prefetchSize=10");consumer = session.createConsumer(queue);(聲明:網(wǎng)上轉(zhuǎn)載)