ActiveMQ高级特性
消息头
JMSDestination:消息发送的目的地,在发送过程中由提供者设置
JMSMessageID:消息的唯一标识符,由提供者设置
JMSDeliveryMode:消息持久化。包含DeliveryMode.PERSISTENT或者DeliveryMode.NON_PERSISTENT
JMSExpiration:消息失效的时间。单位为毫秒,0表示不会过期,默认为0
JMSPriority:消息优先级。0-4为普通,5-9位加急。不一定保证优先级高的先发,只保证加急消息发送先于普通消息。默认为4
JMSCorrelationID:用来链接响应消息与请求消息,由发送者的JMS程序设置
只有JMSCorrelationID,JMSReplyTo,JMSType可以被生产方修改
消息体
TextMessage:字符串
MapMessage:键值对
ObjectMessage:一个序列化的java对象
注:发送的对象必须实现序列化,且消费者与生产者的对象目录结构得相同
ActiveMQ5.12后,ActiveMQ不接受自定义序列化,需要将对象加入到信任的列表
spring.activemq.packages.trust-all:true
BytesMessage:一个字节的数据流
StreamMessage:java原始值的数据流
JMS消息属性
用户可以给消息设置自定义属性
message.setStringProperty("Property", property);
JMS消息持久化
消息持久化有三种消息存储方式:
1)Memory消息存储-基于内存的消息存储(重启会导致消息遗失)
修改yml配置文件:jms.template.delivery-mode=non_persistent
2)基于日志的消息存储,kahaDB是ActiveMQ默认的日志存储方式
修改yml配置文件:jms.template.delivery-mode=persistent
消息自动存储到 activemq/data/kahandb 下
3)基于JDBC的消息存储
修改yml配置文件:jms.template.delivery-mode=persistent
修改conf/activemq.xml
<bean name="mysql-ds" class="com.alibaba.druid.pool.druidDataSource" destory-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/db_activemq" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
删除kehaDB适配器,加入jdbc的适配器
<persistenceAdapter>
<jdbcPersistenceAdapter dataSource="#mysql-ds">
<persistenceAdapter>
导入jdbc和druid的jar包到lib下
消息事务
保证消息传递原子性的一个重要特征(一组消息要么全到达服务器,要么都不到达服务器)
生产者、消费者、消息服务器都支持事务性,ActiveMQ主要偏向生产者
消息确认机制
JMS消息只有在被确认值之后,才认为已经被成功消费,提供方才会将消息从队列中移除。
成功消费通常包含三个阶段:客户接收、处理、消息确认。
在事务性会话中,当一个事务被提交时,消息确认自动发生,在非事务性会话中,通常有三种模式:
1)Session.AUTO_ACKNOWLEDGE: 自动确认
2)Session.CLIENT_ACKNOWLEDGE:手动确认(一组消息中其中一个消息被确认,即全部被确认)
调用message.acknowledge();
3)Session.DUPS_ACKNOWLEDGE:延迟确认(使用较少)
消息投递方式
异步投递
可以容忍一些信息的丢失,Producer.send()方法不会被堵塞。
同步投递
当消息生产者使用持久(persistent)传递模式发送消息时,Producer.send()方法会被堵塞,知道broker发送一个确认消息给生产者,这个确认消息表示broker已经成功接收消息并存入二级存储中。
延迟投递
延迟一段时间,再进行发送
定时投递
启动类上使用@EnableScheduling,生产者方法上使用@Scheduled(fixedDelay = 1000)
死信队列 DLQ Dead Letter Queue
当一个消息被重发超过6次(缺省值为6)时,会给broker发送一个"poison ack",这个消息被认为是 a poison pill,这是broker会将这个消息发送到死信队列,以便后续处理。
出现情况:
A transacted session is used and rollabck() is called. 事务操作调用rollback()
A transacted session is closed before commit is called. 事务操作在提交前关闭
A session is using CLIENT_ACKNOWLEDGE and Session.recover() is called. 使用手动确认机制
注:
1)缺省持久消息过期,会被送到DLQ,非持久化消息不会送到DLQ
2)缺省的死信队列是ActiveMQ.DLQ
问题1:ActiveMQ宕机怎么办?
设置zookeeper或ActiveMQ集群
问题2:如何防止消费方消息重复消费
数据库操作,则记录消息唯一标识符(JMSMessageID),非数据库操作可借用第三方应用redis记录消费记录。
问题3:如何防止消息丢失?
1)在生产者和消费者使用事务
2)在消费者采用手动消息确认(ACK)
3)消息持久化,例如JDBC或日志
问题4:什么事死信队列?
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理