ActiveMQ的消息持久化机制有JDBC,AMQ,JDBC,KahaDB和LevelDB,无论使用哪种持久化方式,消息的存储逻辑都是一致的。
Queue类型的持久化机制
topic类型持久化机制:
将消息存储到数据库中,例如:MySQL、SQL Server 、Oracle、DB2等
基于文件的存储方式,它具有写入速度快和容易恢复的特点,但是由于其重建索引时间过长,而且索引文件占用磁盘空间过大,所以不推荐使用。
从ActiveMQ 5.4开始默认的持久化方式,KahaDB恢复时间远远小于其前身AMQ并且使用更少的数据文件,所以可以完全替代AMQ。
kibaDB关键配置参数:
1、indexWriteBatchSize 批量刷盘的大小 默认1000
2、indexCatchSize 索引信息存在缓存中的大小 默认10000
3、journalMaxFileLength 单个数据文件的大小 默认 32mb
4、enableJournalDiskSyncs 写入文件的方式 默认同步 建议异步 5.14后改为journalDiskSyncStrategy默认为aways
LevelDB是Google开发的一套用于持久化数据的高性能类库。Level并不是一种服务,用户需要自行实现Server。是单进程的服务,能够处理十亿级别规模Key-Value型数据,占用内存小。
特点:1、基于KV存储 2、key值有序存储 3、操作接口简单 4、支持数据快照 5、支持数据压缩
结构:
配置LevelDB
修改配置文件¥{ACTIVEMQ_HOME}/conf/activemq.xml
创建会话时,
第一个参数:是否支持事务,如果为true,则会忽略第二个参数,被jms服务器设置为SESSION_TRANSACTED
第一个参数为false时,第二个参数的值可为Session.AUTO_ACKNOWLEDGE,Session.CLIENT_ACKNOWLEDGE,DUPS_OK_ACKNOWLEDGE其中一个。
Session.AUTO_ACKNOWLEDGE为自动确认,客户端发送和接收消息不需要做额外的工作。哪怕是接收端发生异常,也会被当作正常发送成功。
Session.CLIENT_ACKNOWLEDGE为客户端确认。客户端接收到消息后,必须调用javax.jms.Message的acknowledge方法。jms服务器才会当作发送成功,并删除消息。
DUPS_OK_ACKNOWLEDGE允许副本的确认模式。一旦接收方应用程序的方法调用从处理消息处返回,会话对象就会确认消息的接收;而且允许重复确认。
消费者开启事务后,接收到消息后,需要手动提交事务,否则broker上的消息不会被真正消费;
事务开启且未被提交,同时我们又有rollback的时候,消息会进行重发,重发次数默认为6次;
生产者开启事务后,消息发送后,提交事务后,broker上的消息才能发送到消费者;
除了事务可以进行重发,consumer中带有消息重发策略,可以自定义重发规则;
除了消息重发消费者还带有许多功能,具体资料如下:
异步分发 http://activemq.apache.org/consumer-dispatch-async.html
独占消费 http://activemq.apache.org/exclusive-consumer.html
优先级消费 http://activemq.apache.org/consumer-priority.html
持久订阅者 http://activemq.apache.org/manage-durable-subscribers.html
消费分组 http://activemq.apache.org/message-groups.html
消息重发 http://activemq.apache.org/redelivery-policy.html
消息追溯 http://activemq.apache.org/retroactive-consumer.html
消息过滤 http://activemq.apache.org/selectors.html
慢消费者处理 http://activemq.apache.org/slow-consumer-handling.html
订阅恢复策略 http://activemq.apache.org/subscription-recovery-policy.html
永久订阅者:
持久订阅时,客户端向JMS 注册一个识别自己身份的ID(clientId必须有)
当这个客户端处于离线时,JMS Provider 会为这个ID 保存所有发送到主题的消息
当客户再次连接到JMS Provider时,会根据自己的ID 得到所有当自己处于离线时发送到主题的消息。
tips: ActiveMQ.Advisory开头的消息是activemq提供的一个管理消息推送
http://activemq.apache.org/advisory-message.html
虚拟主题:https://www.cnblogs.com/jiangxiaoyaoblog/p/5659734.html
http://activemq.apache.org/what-is-the-difference-between-a-virtual-topic-and-a-composite-destination.html
消费者异步调度:
从ActiveMQ v4开始,消费者异步调度的配置更加灵活,可以在连接URI、Connection和ConnectionFactory上进行配置,而在以前的版本中,只能在broker服务器上配置。
可以在broker的配置中,通过disableAsyncDispatch属性禁用transportConnector上的异步调度,禁用这个传输连接后,在客户端将无法开启。
通过这种灵活的配置,可以实现为较慢的消费者提供异步消息传递,而为较快的消费者提供同步消息传递。
使用同步消息的缺点是:如果向较慢的消费者发送消息时,可能造成生产者阻塞,从而导致MQ中数据过多,生产者无法传入MQ。
配置代码如下:
//Connection层级
// 在连接上设置是否异步分发,作用于通过此链接创建的所有session
((ActiveMQConnection) conn).setDispatchAsync(false);
// 在队列上设置consumer.dispatchAsync是否异步分发,将仅作用于此队列
// http://activemq.apache.org/destination-options.html
Destination destination = session.createQueue("queue1?consumer.dispatchAsync=false");
//ConnectionFactory层级
// 在连接工厂设置是否异步分发,作用于通过此工厂创建的所有连接
connectionFactory.setDispatchAsync(false);
优先级消费:
ActiveMQ支持消费者优先级
优先级值的范围是:0-127。最高优先级是127。默认优先级是0
独占消费
独占消费是在队列层面使用,当某个队列有多个消费者开启独占模式后,此队列将会被第一个消费者占用,只有第一个消费者才能从这个队列获取消息;未开启时,是多个消费者平均消费
// 在队列上设置consumer.exclusive
// http://activemq.apache.org/destination-options.html
Destination destination = session.createQueue("queue1?consumer.exclusive=true");
消费分组–消费者
两个消费者同时消费同一个队列的时候,两个消费者就属于同一个分组,此时mq的消息就不会重复发送,会发送到其中一个消费者;
消费分组–生产者
通过message.setStringProperty(“JMSXGroupID”,“GroupA”);可以创建一个分组。
同一个组的消息,只会发送到同一个消费者,直到Consumer被关闭
消息追溯
使消费者可以接收到历史的topic消息,需要在activemq.xml中给主题设置恢复策略配置
...
在创建主题时,传入consumer.retroactive=true参数,即可接收到所有满足恢复策略的历史消息
// http://activemq.apache.org/destination-options.html
Topic destination = session.createTopic(topic + “?consumer.retroactive=true”);
消息过滤
消费者接收消息时,支持根据消息属性进行条件过滤,条件为字符串,语法和SQL的where条件类似
复合目标
如果需要将一条消息发送到多个不同的目标,可以在创建目标时,通过","来分隔多个目标。
例如:queue1,queue2,queue3
如果需要匹配目标类型,可以通过增加topic://或queue://前缀来实现。例如在队列上发送消息,同时也发送到主题上:queue1,topic://topic1
虚拟目标
通过此示例演示通过虚拟目标实现持久订阅的功能,是对持久订阅的补充,但是只能有一个链接进行持久订阅,很容易失去高可用性,虚拟目标将topic改为类似于queue的状态,对topic进行映射,订阅者就可以成为一个集群,提高了高可用性的。