ActiveMQ的安裝
安裝要求:
部署需要jdk1.5及以上,編譯需要jdk1.5(java5)及以上
Java的環境變量(JAVA_HOME)必須設置,即jdk安裝的目錄,比如c:\Program Files\jsdk.1.6
下載ActiveMQ:http://activemq.apache.org/download.html
解壓,如圖:
運行bin文件夾下的activemq.bat,出現如下圖所示:
驗證是否運行成功:
在瀏覽器中輸入:http://localhost:8161/admin/,出現如下圖所示表示成功:
此時,ActiveMQ已經安裝完成了,接下來配置登錄監視控制檯的用戶名和密碼。
打開conf文件夾下的jetty.xml,找到
把authenticate屬性的值改成true即可,重啓activemq.bat,再登錄監視控制檯,就需要輸入密碼了,默認的用戶名和密碼是admin/admin。roles屬性指的是登錄的用戶角色,這些登錄的用戶在jetty-realm.properties配置。
修改web的訪問端口,在jetty.xml找到一下配置,修改8161即可。
ActiveMQ的運行日誌存放在data文件夾下的activemq.log中。
Linux和Aix系統下的安裝:
解壓:tar zxvf activemq-x.x.x.tar.gz,進入bin文件夾,運行:./activemq start &,也可以只運行:./activemq console。
驗證方式和安全性配置和windows下的配置一樣。
ActiveMQ消息持久化
在broker中設置屬性persistent=”true”(默認是true),同時發送的消息也應該是persitent類型的。ActiveMQ消息持久化有三種方式:AMQ、KahaDB、JDBC。
1、AMQ
AMQ是一種文件存儲形式,它具有寫入速度快和容易恢復的特點。消息存儲在一個個文件中,文件的默認大小爲32兆,如果一條消息的大小超過了32兆,那麼這個值必須設置大點。當一個存儲文件中的消息已經全部被消費,那麼這個文件將被標識爲可刪除,在下一個清除階段,這個文件被刪除。默認配置如下:
AMQ的屬性:
屬性名稱 | 默認值 | 描述 |
directory | activemq-data | 消息文件和日誌的存儲目錄 |
useNIO | true | 使用NIO協議存儲消息 |
syncOnWrite | false | 同步寫到磁盤,這個選項對性能影響非常大 |
maxFileLength | 32mb | 一個消息文件的大小 |
persistentIndex | true | 消息索引的持久化,如果爲false,那麼索引保存在內存中 |
maxCheckpointMessageAddSize | 4kb | 一個事務允許的最大消息量 |
cleanupInterval | 30000 | 清除操作週期,單位ms |
indexBinSize | 1024 | 索引文件緩存頁面數,缺省爲1024,當amq擴充或者縮減存儲時,會鎖定整個broker,導致一定時間的阻塞,所以這個值應該調整到比較大,但是代碼中實現會動態伸縮,調整效果並不理想。 |
indexKeySize | 96 | 索引key的大小,key是消息ID |
indexPageSize | 16kb | 索引的頁大小 |
directoryArchive | archive | 存儲被歸檔的消息文件目錄 |
archiveDataLogs | false | 當爲true時,歸檔的消息文件被移到directoryArchive,而不是直接刪除 |
2、KahaDB
KahaDB是基於文件的本地數據庫儲存形式,雖然沒有AMQ的速度快,但是它具有強擴展性,恢復的時間比AMQ短,從5.4版本之後KahaDB做爲默認的持久化方式。默認配置如下:
KahaDB的屬性:
property name | default value | Comments |
directory | activemq-data | 消息文件和日誌的存儲目錄 |
indexWriteBatchSize | 1000 | 一批索引的大小,當要更新的索引量到達這個值時,更新到消息文件中 |
indexCacheSize | 10000 | 內存中,索引的頁大小 |
enableIndexWriteAsync | false | 索引是否異步寫到消息文件中 |
journalMaxFileLength | 32mb | 一個消息文件的大小 |
enableJournalDiskSyncs | true | 是否講非事務的消息同步寫入到磁盤 |
cleanupInterval | 30000 | 清除操作週期,單位ms |
checkpointInterval | 5000 | 索引寫入到消息文件的週期,單位ms |
ignoreMissingJournalfiles | false | 忽略丟失的消息文件,false,當丟失了消息文件,啓動異常 |
checkForCorruptJournalFiles | false | 檢查消息文件是否損壞,true,檢查發現損壞會嘗試修復 |
checksumJournalFiles | false | 產生一個checksum,以便能夠檢測journal文件是否損壞。 |
5.4版本之後有效的屬性: | ||
archiveDataLogs | false | 當爲true時,歸檔的消息文件被移到directoryArchive,而不是直接刪除 |
directoryArchive | null | 存儲被歸檔的消息文件目錄 |
databaseLockedWaitDelay | 10000 | 在使用負載時,等待獲得文件鎖的延遲時間,單位ms |
maxAsyncJobs | 10000 | 同個生產者產生等待寫入的異步消息最大量 |
concurrentStoreAndDispatchTopics | false | 當寫入消息的時候,是否轉發主題消息 |
concurrentStoreAndDispatchQueues | true | 當寫入消息的時候,是否轉發隊列消息 |
5.6版本之後有效的屬性: | ||
archiveCorruptedIndex | false | 是否歸檔錯誤的索引 |
從5.6版本之後,有可能發佈通過多個kahadb持久適配器來實現分佈式目標隊列存儲。什麼時候用呢?如果有一個快速的生產者和消費者,當某一個時刻生產者發生了不規範的消費,那麼有可能產生一條消息被存儲在兩個消息文件中,同時,有些目標隊列是危險的並且要求訪問磁盤。在這種情況下,你應該用通配符來使用mKahaDB。如果目標隊列是分佈的,事務是可以跨越多個消息文件的。
每個KahaDB的實例都可以配置單獨的適配器,如果沒有目標隊列提交給filteredKahaDB,那麼意味着對所有的隊列有效。如果一個隊列沒有對應的適配器,那麼將會拋出一個異常。配置如下:
如果filteredKahaDB的perDestination屬性設置爲true,那麼匹配的目標隊列將會得到自己對應的KahaDB實例。配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
<persistenceAdapter>
<mKahaDBdirectory="${activemq.base}/data/kahadb">
<filteredPersistenceAdapters>
<!--kahaDB
per destinations-->
<filteredKahaDBperDestination="true">
<persistenceAdapter>
<kahaDBjournalMaxFileLength="32mb"/>
</persistenceAdapter>
</filteredKahaDB>
</filteredPersistenceAdapters>
</mKahaDB>
</persistenceAdapter>
|
3、JDBC
配置JDBC適配器:
dataSource指定持久化數據庫的bean,createTablesOnStartup是否在啓動的時候創建數據表,默認值是true,這樣每次啓動都會去創建數據表了,一般是第一次啓動的時候設置爲true,之後改成false。
MYSQL持久化bean
SQL Server持久化bean
Oracle持久化bean
DB2持久化bean
1
2
3
4
5
6
7
8
|
<beanid="db2-ds"class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<propertyname="driverClassName"value="com.ibm.db2.jcc.DB2Driver"/>
<propertyname="url"value="jdbc:db2://hndb02.bf.ctc.com:50002/activemq"/>
<propertyname="username"value="activemq"/>
<propertyname="password"value="activemq"/>
<propertyname="maxActive"value="200"/>
<propertyname="poolPreparedStatements"value="true"/>
</bean>
|
ActiveMQ消息發送與接收
配置完了持久化之後,我們就可以使用代碼來發送和接收ActiveMQ中的消息了,我這裏配置的持久化是KahaDB。
需要導入的jar包:
一段發送消息的代碼:
執行了上面的發送方法之後,在ActiveMQ的監視控制可以看到有一個test隊列,並且有一條消息,如圖:
點擊隊列名test,然後點擊消息ID即可查看消息內容,如圖:
如果DeliveryMode沒有設置或者設置爲NON_PERSISTENT,那麼重啓MQ之後消息就會丟失。
一段接收消息的代碼:
執行了上面的接收方法之後,在ActiveMQ的監視控制可以看到test隊列的消息已經被消費了,如圖:
這裏的代碼只是測試用,在正式開發中一般與Spring結合使用jmsTemplate來發送消息,現實JMS的MessageListener來監聽消息。
ActiveMQ配置安全性
監視ActiveMQ的方式有多種,在第一部分中已經說到了Web監視控制檯,設置登錄用戶名和密碼,這裏再說一下JMX監控。運行了ActiveMQ之後,再運行jdk自帶的jconsole即可以看到ActiveMQ的進程,如圖:點擊連接之後就可以看到ActiveMQ的運行情況。默認情況下是不需要用戶名和口令的,修改activemq.bat,找到
修改成
Linux下的找到:
去掉註釋即可。
重啓ActiveMQ之後,在用jconsole連接就需要輸入用戶名和密碼,jmx.access文件配置用戶的訪問權限readonly和readwrite,admin readwrite表示用戶admin具有讀寫權限。Jmx.password文件配置用戶的密碼,admin activemq 表示admin用戶的密碼是activemq。
除了監視臺可以設置用戶名和密碼之後,ActiveMQ也可以對各個主題和隊列設置用戶名和密碼,配置如下:
simpleAuthenticationPlugin中設置用戶名、密碼和羣組,authorizationPlugin設置主題和隊列的訪問羣組,“>”表示所有的主題或者隊列。上面的配置中添加了一個testUser,屬於羣組testGroup,同時設置test這個隊列的訪問讀寫權限爲testGroup,當然admins也可以訪問的,因爲admins是對所有的隊列都有訪問權限。將第三部分代碼中的設置用戶名和密碼改成剛剛添加的用戶testUser,如果密碼不正確,將會拋出User name or password is invalid.異常,如果testUser所屬的羣組不能訪問test隊列,那麼會拋出User guest is not authorized to write to: queue://test異常。需要注意的是所有的羣組都需要對以ActiveMQ.Advisory爲前綴的主題具有訪問權限。
ActiveMQ負載均衡
ActiveMQ可以實現多個mq之間進行路由,假設有兩個mq,分別爲brokerA和brokerB,當有一條消息發送到brokerA的隊列test中,有一個客戶端連接到brokerB上,並且要求獲取test隊列的消息時,brokerA中隊列test的消息就會路由到brokerB上,反之brokerB的消息也會路由到brokerA。
靜態路由配置,brokerA不需要特別的配置,brokerB需要配置networkConnectors節點,具體配置如下:
靜態路由支持failover,如:static:failover://(tcp://host1:61616,tcp://host2:61616)。
動態路由配置,每個mq都需要配置如下:
注意:networkConnectors需要配置在persistenceAdapter之前。
重啓ActiveMQ,可以看到brokerA的日誌如圖:
networkConnector的屬性請參照:http://activemq.apache.org/networks-of-brokers.html
ActiveMQ主備配置
ActiveMQ的主備有三種方式:純Master/Slave、文件共享方式、數據庫共享方式。
1、純Master/Slave
這種方式的主備不需要對Master Broker做特殊的配置,只要在Slave Broker中指定他的Master就可以了,指定Master有兩種方式,最簡單的配置就是在broker節點中添加masterConnectorURI=”tcp://localhost:61616″即可,還有一種方式就是添加一個services節點,可以指定連接的用戶名和密碼,配置如下:
純Master/Slave只允許一個Slave連接到Master上面,也就是說只能有2臺MQ做集羣,同時當Master掛了之後需要停止Slave來恢復負載。
2、數據庫共享方式
這種方式的主備採用數據庫做消息的持久化,支持多個Slave,所有broker持久化數據源配置成同一個數據源,當一個broker獲取的數據庫鎖之後,其他的broker都成爲slave並且等待獲取鎖,當master掛了之後,其中的一個slave將會立刻獲得數據庫鎖成爲master,重啓之前掛掉的master之後,這個master也就成了slave,不需要停止slave來恢復。由於採用的是數據庫做爲持久化,它的性能是有限的。
3、文件共享方式
這種方式的主備具有和數據庫共享方式的負載一樣的特性,不同的是broker的持久化採用的是文件(我這裏用KahaDB),slave等待獲取的鎖是文件鎖,它具有更高的性能,但是需要文件共享系統的支持。
Window下共享KahaDB持久化的目錄,配置如下:
Linux下需要開啓NFS服務,具體操作如下:
創建共享目錄(192.168.0.1):
1、 修改etc/exports,添加需要共享的目錄:/opt/mq/data *(rw,no_root_squash)
2、 啓動NFS服務 service nfs start/restart
3、 查看共享 showmount –e
4、 NFS服務自啓動 chkconfig –level 35 nfs on
掛載共享目錄(192.168.0.2):
1、 掛載:mount –t nfs 192.168.0.1:/opt/mq/data /opt/mq/data
2、 啓動自動掛載:在etc/fstab文件添加10.175.40.244:/opt/mq/data /opt/mq/data nfs defaults 0 0
然後指定KahaDB的持久化目錄爲/opt/mq/data即可。
AIX系統的文件共享和Linux類似,也是啓動NFS服務。
注意:如果Master服務器宕機了,Slave是不會獲得文件鎖而啓動,直到Master服務器重啓。
Window下Master上有Slave連接時如圖:
客戶端連接的brokerURL爲failover:(tcp://localhost:61616,tcp://localhost:61617)。用第三部分的代碼測試,先向Master Broker發送一個消息,然後關閉master,運行獲取消息的方法,即可獲取之前發送的消息。
ActiveMQ性能優化
1、目標策略
在節點destinationPolicy配置策略,可以對單個或者所有的主題和隊列進行設置,使用流量監控,當消息達到memoryLimit的時候,ActiveMQ會減慢消息的產生甚至阻塞,destinationPolicy的配置如下:
producerFlowControl表示是否監控流量,默認爲true,如果設置爲false,消息就會存在磁盤中以防止內存溢出;memoryLimit表示在producerFlowControl=”true”的情況下,消息存儲在內存中最大量,當消息達到這個值時,ActiveMQ會減慢消息的產生甚至阻塞。policyEntry的屬性參考:http://activemq.apache.org/per-destination-policies.html
當producer發送的持久化消息到達broker之後,broker首先會把它保存在持久存儲中。接下來,如果發現當前有活躍的consumer,如果這個consumer消費消息的速度能跟上producer生產消息的速度,那麼ActiveMQ會直接把消息傳遞給broker內部跟這個consumer關聯的dispatch queue;如果當前沒有活躍的consumer或者consumer消費消息的速度跟不上producer生產消息的速度,那麼ActiveMQ會使用Pending Message Cursors保存對消息的引用。在需要的時候,Pending Message Cursors把消息引用傳遞給broker內部跟這個consumer關聯的dispatch queue。以下是兩種Pending Message Cursors:
VM Cursor:在內存中保存消息的引用。
File Cursor:首先在內存中保存消息的引用,如果內存使用量達到上限,那麼會把消息引用保存到臨時文件中。
在缺省情況下,ActiveMQ 會根據使用的Message Store來決定使用何種類型的Message Cursors,但是你可以根據destination來配置Message Cursors。
對於topic,可以使用的pendingSubscriberPolicy 有vmCursor和fileCursor。可以使用的PendingDurableSubscriberMessageStoragePolicy有
vmDurableCursor 和 fileDurableSubscriberCursor;對於queue,可以使用的pendingQueuePolicy有vmQueueCursor 和 fileQueueCursor。
Message Cursors的使用參考:http://activemq.apache.org/message-cursors.html
2、存儲設置
設置消息在內存、磁盤中存儲的大小,配置如下:
memoryUsage表示ActiveMQ使用的內存,這個值要大於等於destinationPolicy中設置的所有隊列的內存之和。
storeUsage表示持久化存儲文件的大小。
tempUsage表示非持久化消息存儲的臨時內存大小。
使用過程中出現的問題
報錯日誌:Usage Manager Store is Full, 100% of 1073741824. Stopping producer (ID:db01-48754-1336034955132-0:5:1:1) to prevent flooding queue://queue.land.group. See http://activemq.apache.org/producer-flow-control.html for more info (blocking for: 1s) | org.apache.activemq.broker.region.Queue | ActiveMQ Transport: tcp:///172.24.99.41:44716
這是由於我們在配置文件中設置了storeUsage ,當存儲的消息文件(log文件)超過了這值就會報這個異常,在官方網站看到說消息文件不刪除是5.3版本的一個bug,在5.5版本的時候已經被解決了,但是我們使用的是5.5.1版本啊,然後在看存儲下來的消息文件,文件名不是連續的,那麼說明其中還是有被刪除的,後來在評論中看到Jeff Genender 說的這個可能是ActiveMQ的線程調度問題,只要不使用線程調度就可以了,在broker中設置屬性schedulerSupport=”false” ,這樣消息文件就會自動在cleanup階段刪除了。