前言
MQ是現在大型系統架構中必不可少的一個重要中間件,之前有偏文章
《MQ(消息隊列)常見的應用場景解析》介紹過MQ的應用場景,現在流行的幾個MQ是rabbitmq,rocketma,kafka,這幾個MQ比較最容易找到相關的文章,而也有些系統使用的是activemq,因activemq是相對比較傳統的MQ,在使用過程中還是會遇到很多坑,這裡簡單列舉幾個大家可能會遇到的問題,把自己使用acitvemq的經驗和大家分享一下。
Mysql 持久化
現在大家使用MQ,基本都是會把資料進行持久化,MQ預設存儲持久化資料使用kahaDB,但是鑒于大家對mysql比較熟悉,很多人會選擇mysql進行資料的持久化,因為mysql檢視資料還是比較友善的。如果需要把持久化方式改為mysql,則需要修改如下配置:
<persistenceAdapter>
<jdbcPersistenceAdapter dataDirectory="${activemq.data}" dataSource="#mysql-ds" createTablesOnStartup="false" useDatabaseLock="false"/>
<!-- 下面是預設的kahaDB方式,注釋掉 -->
<!-- <kahaDB directory="${activemq.data}/kahadb"/> -->
</persistenceAdapter>
這裡的配置有幾個地方大家需要關注下:
配置 | 說明 |
---|---|
dataDirectory | 需要配置和broker 的dataDirectory 一緻 |
dataSource | 資料源的選擇,關聯資料庫的具體配置,下文會具體說明 |
useDatabaseLock | 是否使用資料庫鎖,主要是在程式啟動的時候會同步查詢資料,導緻資料庫鎖 |
還需要配置資料庫的連接配接、賬号、密碼等:
<!-- MySql DataSource Setup -->
<bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://0.0.0.0:3306/activemq?relaxAutoCommit=true"/>
<property name="username" value="root"/>
<property name="password" value="******"/>
<property name="poolPreparedStatements" value="true"/>
</bean>
其中,id 名和上文提到的datasource應該是一樣的。否則,不知道連接配接哪個執行個體。
資料庫連接配接池問題
啟動activemq如果提示資料庫的連接配接池有問題,這可能是少了lib,增加
- mysql-connector-java-5.1.30.jar
- commons-dbcp2-2.1.1.jar
- commons-pool2-2.4.2.jar
三個包,放到lib目錄即可
管理界面無法打開
如果正常啟動了,但是管理界面無法啟動,那麼需要修改下管理界面的資料庫連接配接。
使用MQ主要原因之一是MQ性能比傳統關系資料庫性能要好,但是把MQ資料存儲的mysql其實不是一個很好的選擇,反其道而行之,雖然這樣用的團隊不少,但是強烈推薦不要這麼做。還是用預設的存儲方式,確定性能為主。
activeMQ過期配置
前文說過,activemq性能本來就不是最優的,特别是使用了mysql作為資料庫存儲工具後,性能更加不靠譜,是以性能優化,是個重要的工作,定期清理MQ的過期資訊,就顯的非常重要了。
定期清理無效的隊列
配置如下:
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry queue=">" gcInactiveDestinations="true" inactiveTimoutBeforeGC="10000">
<deadLetterStrategy>
<sharedDeadLetterStrategy processExpired="true" expiration="30000"/>
</deadLetterStrategy>
</policyEntry>
<policyEntry topic=">" gcInactiveDestinations="true" inactiveTimoutBeforeGC="10000" >
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="1000"/>
</pendingMessageLimitStrategy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
定期自動清理無效的Topic和Queue,這個配置,隻會清除設定的時間内,沒有被訂閱,同時隊列沒有遺留資料的隊列。
同時,對于boker節點,需要設定schedulePeriodForDestinationPurge 參數,表示多長之間執行一次檢測。
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost01" dataDirectory="${activemq.data}"
useJmx="true" schedulePeriodForDestinationPurge="5000">
設定消息的全局過期時間
開發的時候,大家應該都知道可以設定消息的過期時間,是否有統一設定消息的過期時間呢?
在broker節點下增加如下的配置:
<plugins>
<!-- 86400000 為一天,設定為10天過期 -->
<timeStampingBrokerPlugin ttlCeiling="10000"
zeroExpirationOverride="10000" />
</plugins>
為了便于測試,我設定的是10s,當然,生産環境根據自己的是實際設定的會比較長。過期的時間會進入死信,死信也會沿用此時間,到期後,系統就會自動删除資訊了。
經過我個人的實踐經驗,MQ積累的資料達千萬級别後,性能下降的比較厲害,定期清理MQ的消息,是優化性能非常重要的一個操作。
總結
現如今,MQ的選擇很多,建議還是優先選擇rabbitmq、rocketmq或者是kafka,如果已經選擇activemq,需要持續關注MQ的消費情況,最好能設定過期時間,定期清理消息隊列的資料,避免資料的積累,造成性能的下降。
微信号:itmifen

image