2011-08-17 208 views
7

我目前在使用JMS(即Spring框架JMS和Active MQ)應用程序的帶寬限制功能(請不要問我爲什麼,它不是我的決定)來發送帶有效負載的服務器和服務器之間的消息客戶端。JMS消息大小

我發現很多限制傳入JMS消息的限制方法(但它們都不是基於實際的帶寬負載),但是我沒有找到任何可能的方法來限制傳出的消息流。所以我決定自己寫Leaky bucket algorithm

有什麼方法可以獲得JMS消息的大小嗎?除了'sizeof'在Java中的實現(In Java, what is the best way to determine the size of an object?

+0

爲什麼不限制傳入消息流量 - ActiveMQ允許您在目標上使用producerFlowControl和memoryLimits。我很想知道爲什麼你想限制傳出的消息。此外 - 這種類型的東西不能更好地從坐在經紀人面前的某種應用交付控制器控制(假設你甚至有這種選擇)。 – whaley

+0

我們的客戶希望限制生產商的出站帶寬(假設客戶有100兆帶寬,但他只想使用10兆位)。它讓我瘋狂。 JMS儘可能快地傳遞消息,所以我不太瞭解這種需求。但令人遺憾的是,這不符合我的決定。 – Sorceror

回答

3

由於JMS消息在發送過程中被序列化,因此獲得消息大小的最佳方式是through ObjectOutputStream

private int getMessageSizeInBytes(MessageWrapper message) throws IOException { 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ObjectOutputStream oos = new ObjectOutputStream(baos); 
    oos.writeObject(message); 
    oos.close(); 
    return baos.size(); 
} 
4

我不認爲你有更好的選擇來確定JMS消息的大小,而不是測量它的序列化大小。

但是,如果你願意,你可以添加一些優化。有幾種類型的消息(例如MapMessage,ObjectMessage,TextMessage)。

短信的大小是其文本的長度。地圖信息的大小是其所有字段的總大小。這些字段是基元或java.util.Date,所以測量它們不是問題。 對象消息包含可序列化的對象,因此您可以通過寫入ByteOutputStream來測量其大小。

我認爲如果您使用大多數JMS提供程序的隱藏功能發送延遲的消息,則可以簡化使用JMS實現漏桶。您可以在排隊時測量消息,並決定用戶何時接收消息。 請閱讀這裏的如何發送延遲消息的詳細信息:http://alexradzin.blogspot.com/2010/10/send-delayed-jms-messages.html

+0

+1好想法想想,謝謝.. – Sorceror

1

除了由@AlexR早期評論,BytesMessage有getBodyLength()方法

http://download.oracle.com/javaee/1.4/api/javax/jms/BytesMessage.html#getBodyLength

,你或許可以估算典型通過捕獲使用Session.createMessage()創建的一些對象 - 即沒有有效載荷的JMS消息類型,傳輸頭部大小。我想我會試圖直接使用byte []中的有效負載,使用BytesMessage,如果帶寬非常關鍵,則通過ZipOutputStream進行壓縮。另外,JMS允許提示來抑制消息時間戳和消息ID,這可能有助於減小消息大小,例如

http://download.oracle.com/javaee/1.4/api/javax/jms/MessageProducer.html#setDisableMessageTimestamp%28boolean%29

雖然提供者不需要支持的話,

如果JMS提供者接受此暗示,這些消息必須設置爲空的消息ID;如果提供者忽略提示,消息ID必須設置爲正常的獨特價值

我曾與在WebSphere MQ Everyplace的很有限帶寬JMS工作,並有可能得到的消息尺寸非常小這種方式 - 儘管在這種情況下本地線框格式也針對尺寸進行了優化

+0

帶寬並不重要,我們的客戶只是想管理吞吐量。 +1'getBodyLength()',但我擔心這隻適用於'BytesMessage'實例,我想我沒有.. – Sorceror