前言
MQ 是现在大型系统架构中必不可少的一个重要中间件, 之前有偏文章MQ(消息队列) 常见的应用场景解析 http://www.17ij.com/mquse/ 介绍过 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 的消费情况, 最好能设置过期时间, 定期清理消息队列的数据, 避免数据的积累, 造成性能的下降.
来源: https://www.cnblogs.com/joylee/p/9583127.html