资讯动态

JMS与ActiveMQ实战:消息队列核心概念、代码实践与排错指南

发布时间:2026/10/19 17:10:59 来源:尧图企业网站定制
做后端开发的朋友多少都听过JMS和ActiveMQ这两个词。如果你还没碰过消息中间件第一次看到它们的时候大概率是懵的——JMS到底是个什么标准ActiveMQ和我天天写的Java代码又有什么关系我在某公司做服务端开发时第一次被叫去优化一个日志上报接口业务高峰期Tomcat线程池被打满数据库连接也濒临崩溃。后来引入ActiveMQ做异步削峰才真正把这件事扛过去。也正是那段时间我把JMS和ActiveMQ从概念到代码完整啃了一遍踩了不少坑。这篇文章就是那段时间的学习记录和实战总结给正准备入门或者入门到一半的兄弟们做个参考不管你是学生还是刚转后端没几年的开发者应该都能从中拿走一些直接能用的东西。1. JMS和ActiveMQ到底在解决什么问题1.1 先从一个真实场景说起接口变慢了问题出在哪那年我们公司的日报系统接了一个新需求用户每次操作后需要把行为日志上报给数据分析平台。一开始实现得很直接业务接口里同步调日志服务的HTTP接口日志服务再写入数据库。上线后前两个月一切正常后续接入的业务越来越多日志量翻了几倍问题开始冒头了接口平均响应时间从50毫秒涨到了800毫秒高峰期更是直接超时日志服务一重启业务接口也跟着报错下游抖动直接传导到上游。这个场景应该不少人都有共鸣核心问题就是同步耦合太深。一次用户请求本来只需要做自己的业务结果被迫等一个慢吞吞的日志写入完成。你想想就像你去餐厅点餐服务员非要等到后厨把下一周的食材都备好才开始给你下单——明明只需要把订单递进去就够了。解决思路也很简单把日志消息先丢到一个中间地带让业务接口立刻返回再由后端的消费者慢慢地、批量地去处理这些日志。这个“中间地带”就是消息队列而ActiveMQ就是这样一个中间件。当然这只是最典型的异步解耦场景。消息队列还能干流量削峰的活比如秒杀场景瞬时请求量可能是平时的上百倍直接打到数据库上基本就是秒挂但通过在入口处把请求转成消息慢慢消化系统就能平稳扛过去。还有跨系统数据同步、广播通知、日志收集这些都是消息队列的高频使用场景。搞清楚了这些场景你才会明白JMS和ActiveMQ不是某个框架的花架子而是后端架构里很实在的基础设施。1.2 JMS和ActiveMQ是什么关系一个标准一个实现先说结论JMS是Java定义的一套消息服务API规范ActiveMQ是实现了这套规范的具体产品。打个比方JMS就像JDBCActiveMQ就像MySQL你写代码的时候用的是JDBC的接口底下跑的是MySQL驱动。同理你写JMS代码的时候用的是javax.jms包里的接口底下真正干活的是ActiveMQ的客户端库。这个区分特别重要因为很多人一开始会把它们混为一谈。JMS全称Java Message Service它是Java社区定义的一组接口规定了消息生产者、消费者、消息目的地这些核心模型应该长什么样但不管你底层用的是ActiveMQ还是其他实现规范的消息中间件写出来的代码结构是类似的。ActiveMQ是Apache基金会下的开源项目算是最老牌的消息中间件之一它完整实现了JMS 1.1规范还提供了一些自己的扩展能力。学习的时候我的建议是先以ActiveMQ作为载体去理解JMS规范。因为ActiveMQ部署简单纯Java开发文档多社区里踩坑记录也丰富对新手非常友好。等把JMS这套模型吃透了以后换别的JMS实现或者去学别的消息中间件你会发现很多概念都是相通的学习成本会直线下降。我见过不少人一上来就研究什么分布式消息队列的高可用架构结果连Queue和Topic都分不清这种学习路径其实很亏。1.3 学习JMS的正确路线概念别贪多代码必须上手JMS涉及的概念其实不少但很多是边角料入门阶段根本用不上。我把自己的学习路线整理了一下大致分四个阶段第一阶段理解消息模型搞明白Queue、Topic、消息生产者、消息消费者分别是什么能画出消息流转的草图。第二阶段动手搭建环境把ActiveMQ跑起来用管理控制台看一眼队列里的消息长什么样建立直观感受。第三阶段写代码先写一个点对点模式的生产者和消费者让消息能发能收再写一个发布订阅模式理解两者的区别。第四阶段进阶机制研究事务、消息确认、持久化订阅这些可靠性相关的机制最后带着问题去查官方文档。这么一套走下来基本就能在实际项目里独立使用ActiveMQ了。下面几个章节就按这个路线把每个阶段的关键内容拆开讲清楚代码部分我直接贴出来你照着跑一遍就行。2. JMS核心概念梳理模型、消息结构和可靠性机制2.1 两种消息模型点对点与发布订阅JMS规范里定义了两种消息传递模型这是整个JMS世界的地基就是Queue和Topic。Queue是点对点模型也叫P2P模型。生产者把消息发给一个指定的队列消息队列会保存这些消息直到某个消费者把它取走。一条消息只能被一个消费者消费消费完就没有了不存在多个消费者同时收到同一条消息的情况。这就像去银行柜台办业务你取一个号排队到某个窗口只有这个窗口的员工会处理你的业务别的窗口不会重复办理。如果暂时没有消费者在线消息也不会丢它会安静地待在队列里等消费者上线后取走。这个特性在做任务分发、异步处理时特别实用。Topic是发布订阅模型也叫Pub/Sub模型。生产者把消息发到一个主题上所有订阅了这个主题的消费者都能收到消息。这就像公众号发文你关注了某个公众号作者一发文章所有粉丝的订阅列表里都会有这条消息。不过有个关键区别Topic消息默认不持久化如果消费者当时不在线等它上线后是收不到之前错过的消息的。要让消费者能收到离线期间的消息就得用持久化订阅这个后文专门讲。初学者最容易混淆的地方就是这两个模型的区别。记住一句话Queue是一条消息只给一个消费者大家抢着消费消息被抢走就没了Topic是一条消息广播给所有订阅者每个订阅者都能拿到一份拷贝。把这个逻辑刻在脑子里很多后面的事情就顺了。2.2 一条消息的完整结构消息头、属性和消息体JMS里一条消息不是光秃秃的一串文字它有固定的三部分结构消息头、属性和消息体。消息头是一堆系统自动设置的字段JMS规范里定义了很多标准字段其中最重要的几个是JMSDestination表示消息发往的目的地是Queue还是TopicJMSDeliveryMode表示消息是持久化还是非持久化JMSExpiration表示消息过期时间JMSPriority表示消息优先级还有JMSCorrelationID可以用来关联多条消息比如把请求消息和响应消息关联起来。实际操作中这些字段大部分是消息中间件自动填充的但有些你也可以手动设置比如过期时间。属性部分可以理解为消息的自定义标签分为三类应用属性、JMS定义的属性和消息中间件厂商的特定属性。用得最多的是应用属性你可以设置一些键值对比如消息来源、消息类型、业务ID等。属性的一个重要作用是支持消息筛选消费者可以设置消息选择器只消费满足特定条件的消息。消息体是消息的实际内容JMS定义了五种类型的消息TextMessage承载纯文本最常用MapMessage承载一组键值对ObjectMessage承载序列化后的Java对象BytesMessage承载二进制数据StreamMessage承载原始数据流。第一次用的时候直接选TextMessage就行简单直接后面有需求再研究其他类型。我见过有人非要用ObjectMessage结果对象没实现序列化接口消费者反序列化直接报错绕了一大圈——能用TextMessage解决的事情不要附加多余复杂度。2.3 可靠性三板斧持久化、确认机制和事务消息中间件存在的价值就是帮你把消息可靠地送到消费者手里。JMS提供了三个核心的可靠性保证分别是持久化、消息确认和事务。持久化对应的是JMSDeliveryMode字段。非持久化消息的性能更好因为消息存在内存里但Broker一重启消息就没影了持久化消息会先落盘再确认Broker重启后消息还能恢复。如果消息很重要比如订单、支付回调一定要设置成持久化。ActiveMQ默认的消息发送模式就是持久化这点对新手倒是挺友好。不过持久化也有成本ActiveMQ默认通过KahaDB存储磁盘IO上会有一些开销如果每条消息都是持久化且量又特别大磁盘性能就成了瓶颈这个我在后面性能调优部分还会再讲。消息确认机制是消费者端的可靠性保证。消费者从Broker取走消息后需要告诉Broker“这条消息我处理好了”这样Broker才敢把消息删除。如果消费者取走消息后还没确认就挂了Broker会在消费者重新连接后再次投递这条消息这样就保证了消息至少被消费一次。JMS定义了四种确认模式AUTO_ACKNOWLEDGE自动确认、CLIENT_ACKNOWLEDGE手动确认、DUPS_OK_ACKNOWLEDGE允许重复确认、SESSION_TRANSACTED配合事务使用。默认的自动确认看似省事但如果你在消费者里处理消息需要调外部接口万一消息取回来后还没处理完就自动确认了处理逻辑却失败了这条消息就丢了。这种情况就必须手动确认确保处理成功之后再调用acknowledge方法。事务是更进一步的保证它可以让一批消息的发送或接收要么全部成功要么全部失败。你在Session上开启事务后发送消息不会立即生效要调用session.commit()才会真正提交处理过程中发现异常就调用session.rollback()这批消息会被回滚。把事务和确认机制配合好基本就能在业务上做到不丢消息。3. 环境搭建与两种模式的完整实操3.1 五分钟跑起ActiveMQ安装、启动和控制台验证ActiveMQ的部署算是消息中间件里最简单的了。去Apache官网下载对应操作系统的压缩包我这边以某次用的ActiveMQ 5.15版本为例。解压之后目录里有个bin文件夹Windows环境下直接双击activemq.batLinux或者macOS环境就在终端执行activemq start。这里提醒一句如果用的是macOS解压到/Download这种路径可能会报权限问题把它挪到用户目录下再启动就行。启动成功之后有两个地址要记一下。一个是Broker的服务地址默认是:61616。后面代码里创建连接工厂要填这个地址在这里设置用户名密码的时候注意别搞混端口。另一个是管理控制台默认是:8161打开浏览器访问http://127.0.0.1:8161默认账号密码是admin/admin。控制台里能看到当前有几个Queue、几个Topic消息有没有堆积消费者是不是在线对初学者来说是最直观的验证工具。我第一次启动的时候一直盯着终端等输出以为要看到什么特殊日志才叫启动成功其实只要没报错控制台能打开Broker就是在正常工作了。3.2 点对点模式实践一个Hello World级别的生产者消费者接下来是动手环节。先建一个普通的Java项目把ActiveMQ的客户端jar包引入进来。如果你用的是Maven在pom.xml里加依赖就行activeMQ-client这个jar包就用5.15版本和你装的Broker保持一致就好版本不一致有时候会出现兼容问题。先看生产者代码import org.apache.activemq.ActiveMQConnectionFactory; import javax.jms.*; public class QueueProducer { public static void main(String[] args) throws Exception { // 1. 创建连接工厂指定Broker地址 ActiveMQConnectionFactory factory new ActiveMQConnectionFactory( tcp://127.0.0.1:61616); // 2. 创建连接并启动 Connection connection factory.createConnection(); connection.start(); // 3. 创建会话第一个参数false表示不开启事务 Session session connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // 4. 创建目标队列 Queue queue session.createQueue(demo.queue); // 5. 创建生产者并发送消息这里把持久化模式设为可配置 MessageProducer producer session.createProducer(queue); producer.setDeliveryMode(DeliveryMode.PERSISTENT); for (int i 0; i 5; i) { TextMessage message session.createTextMessage(Hello JMS i); producer.send(message); } System.out.println(消息发送完成); // 6. 关闭资源 producer.close(); session.close(); connection.close(); } }再写消费者import org.apache.activemq.ActiveMQConnectionFactory; import javax.jms.*; public class QueueConsumer { public static void main(String[] args) throws Exception { ActiveMQConnectionFactory factory new ActiveMQConnectionFactory( tcp://127.0.0.1:61616); Connection connection factory.createConnection(); connection.start(); Session session connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue session.createQueue(demo.queue); MessageConsumer consumer session.createConsumer(queue); // 同步接收消息设置3秒超时超过时间返回null while (true) { Message message consumer.receive(3000); if (message null) { break; } if (message instanceof TextMessage) { TextMessage textMessage (TextMessage) message; System.out.println(收到消息 textMessage.getText()); } } consumer.close(); session.close(); connection.close(); } }先运行消费者再运行生产者控制台就能看到五条消息被依次消费。这里有个新手容易忽略的细节connection.start()这一步不能省没有启动连接消费者虽然创建成功了但根本不会接收到任何消息。而且实际项目中连接和会话的创建是有开销的不要每条消息都新建连接应该复用长连接。同步receive的方式虽然在Demo里看着直观但真实项目里更推荐用MessageListener做异步监听代码后面会给。3.3 发布订阅模式实践从群发消息到持久化订阅发布订阅模式和点对点的代码结构几乎一样差别只在两处一是目的地用Topic而不是Queue二是消费者的行为不同。先看一段发布者的代码Topic topic session.createTopic(demo.topic); MessageProducer producer session.createProducer(topic); for (int i 0; i 5; i) { TextMessage message session.createTextMessage(Topic消息 i); producer.send(message); }消费者的创建普通订阅这样写Topic topic session.createTopic(demo.topic); MessageConsumer consumer session.createConsumer(topic);这时候你如果直接运行会发现一个现象先启动消费者、再运行发布者消费者能收到五条消息。但如果你先发消息再启动消费者消费者什么都收不到。这就是我前面说的Topic消息默认不持久化消息发出去没有订阅者接收就直接失效了。很多新手在这里卡很久以为自己代码写错了其实这是发布订阅的默认行为。要想让离线消费者能收到错过的消息就要用持久化订阅。JMS里创建持久化订阅要调用Session的createDurableSubscriber方法传两个参数Topic和订阅ID。同时订阅者的ClientID必须在连接层面先指定否则ActiveMQ会报错。示例代码如下// 必须指定ClientID同一个订阅ID的ClientID要保持一致 connection.setClientID(consumer-001); Session session connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Topic topic session.createTopic(demo.topic); // 第二个参数是订阅名Broker用它在持久化存储里标记这条订阅 MessageConsumer consumer session.createDurableSubscriber(topic, subscriber-001);用了持久化订阅后即使消费者下线Broker也会把主题消息保存下来等消费者重新上线消息会按照订阅关系重新投递。生产环境里广播通知、配置变更推送这类场景千万别忘了用持久化订阅否则消费者一重启关键消息就全错过了。我自己就吃过这个亏有一次做配置推送消费者半夜发布重启正好错过了重启期间的配置变更消息第二天线上配置不对排查了好久才回过味来。4. 进阶实践事务、连接复用和代码细节4.1 Session事务模式一批消息要么全成功要么全失败在实际业务里我们经常需要一批消息一起被消费并完成数据库操作如果中间某条消息处理失败希望前面处理过的也回滚。JMS事务正是为这种场景设计的。开启事务的Session是这样创建的Session session connection.createSession(true, Session.SESSION_TRANSACTED);注意第一个参数传true的时候第二个参数就被忽略规范要求固定传Session.SESSION_TRANSACTED。在这个Session下发送消息消息不会立即到达Broker而是缓存在本地必须调用session.commit()之后才会真正发送。消费者也是一样从Broker取消息后消息会暂存在本地处理成功就commit处理过程中发现异常就rollback消息会被重新投递。我举个实际例子。有一个订单状态同步服务消费者从队列里拿到订单消息需要更新本地数据库然后给上游系统回写一个确认状态。如果只做数据库更新不开启事务消息处理到一半挂了数据库更新成功但回写失败这条消息就被确认掉了后续无法重试。遇到这种要么全做要么全不做的场景就应该开启事务。但要注意事务和数据库操作要放在同一个事务边界里比较难协调因为JMS事务和数据库事务是两套体系。经验做法是消息的commit和数据库事务要么同时成功要么协调回滚可以用一个统一的事务管理器去管理比如Spring的JmsTransactionManager配合DataSourceTransactionManager做分布式事务协调。这块有点深入门阶段理解“事务可以保证消息批量可靠处理”这个点就够了。4.2 消息确认时机自动确认和手动确认该怎么选前面提到AUTO_ACKNOWLEDGE很方便但某些场景下它是陷阱。我详细说一下它的工作方式消费者调用receive方法拿到消息只要消息一交给应用程序Session就立刻向Broker确认压根不管后面的业务处理代码有没有执行完。如果你拿到消息之后调了一个远程接口结果远程接口超时本地处理抛出异常——来不及了消息已经被确认了Broker不会重新投递。换到CLIENT_ACKNOWLEDGE模式则是你拿到消息后只有自己主动调用message.acknowledge()Broker才会收到确认。所以我的建议是如果消费者只是把消息简单打印或者写入本地日志自动确认就够了如果消息处理涉及业务逻辑比如调接口、写数据库、做计算一律优先考虑手动确认而且要在所有业务处理成功之后再确认。手动确认的写法是Session session connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); MessageConsumer consumer session.createConsumer(queue); consumer.setMessageListener(new MessageListener() { Override public void onMessage(Message message) { try { // 处理业务逻辑写库、调接口、写文件 process(message); // 所有逻辑处理成功后再确认 message.acknowledge(); } catch (Exception e) { // 处理失败不确认Broker会重新投递 log.error(消息处理失败等待重试, e); } } });这里有个细节在CLIENT_ACKNOWLEDGE模式下调用任一消息的acknowledge方法会把当前Session里所有未确认的消息都一起确认掉。也就是说如果一个Session里同时消费了10条消息你只想确认其中1条但实际上10条都会被确认。这是JMS规范里定义的行为很多人刚开始不知道就会产生消息丢失的误解。如果确实需要对每条消息单独确认就必须一个消息一个Session或者改用ActiveMQ扩展的个别确认机制。4.3 资源关闭顺序和连接工厂的细节JMS资源有明确的层级关系ConnectionFactory创建ConnectionConnection创建SessionSession创建Producer和Consumer。关闭资源的时候顺序要反过来先关Producer和Consumer再关Session最后关Connection。之前遇到有人只关Connection不关其他资源这种情况下大多数连接池还算能容忍但在一些版本里会出现Broker端连接未释放的告警。连接工厂还有一个很实用的坑要提醒ActiveMQ的ConnectionFactory默认创建的是普通连接不支持自动重连。如果Broker在运行过程中重启了连接就会断开应用程序需要手动重新创建连接。对生产环境来说这很难接受所以一定要用ActiveMQ提供的failover协议连接地址写成这样ActiveMQConnectionFactory factory new ActiveMQConnectionFactory( failover:(tcp://127.0.0.1:61616)?initialReconnectDelay100maxReconnectAttempts10);failover协议会自动在连接断开后重新连接还能配置重连间隔和重试次数。我的一个项目里用普通连接凌晨Broker做一次滚动重启结果一堆消费者全部失联第二天排查才发现是连接没有自动恢复机制。从那以后我写的所有ActiveMQ连接都统一用failover协议这个习惯算是踩坑踩出来的。5. 常见问题与排查经验实录5.1 消费者收不到消息优先排查这四个方面消费者收不到消息是最常见的故障我总结了一套排查顺序照着做基本能定位。第一先确认Broker和消费者之间网络是不是通的。用telnet命令测一下61616端口通不通如果端口不通防火墙、安全组都是嫌疑对象特别要注意云服务器上还要看安全组规则有时候本地端口放行了远程IP没放行一样连不上。第二去管理控制台看消息的状态。打开8161端口的管理页面找到对应的Queue看Enqueue count和Dequeue count。如果Enqueue是0说明生产者根本没把消息发进来问题在生产端如果Enqueue有值但Dequeue一直不涨说明消息进了队列但消费者没取走问题在消费端如果两者都在涨消息就没丢只是处理速度慢。第三看消费者连接是否建立。控制台里能看到有哪些消费者连接了Broker如果消费者列表是空的说明消费端的代码根本没跑到创建消费者的那一步或者连接被阻塞了。特别要检查connection.start()有没有被遗忘这个错误太常见了。第四确认消息目的地是否一致。生产者创建的Queue名称和消费者创建的Queue名称必须完全一致多一个空格、大小写不同都收不到。Topic也是一样还要确认订阅ID是否是持久化订阅。我还遇到过一种情况消息设置了过期时间消费者处理太慢消息还没被消费就过期了控制台里Expired count会显示过期数量这时候就该调大过期时间或者看看消费者为什么这么慢。5.2 消息重复消费和消息丢失如何尽量规避消息重复消费几乎是所有消息系统都绕不开的问题。原因在于消费者处理消息的过程中挂了Broker没收到确认等消费者恢复后会重新投递这条消息而之前那条消息可能已经被处理了一部分。所以消息中间件保证的往往是“至少一次投递”而不是“恰好一次”。要想让业务不重复通常需要在消费端做幂等处理通过唯一业务ID查一下数据库已经处理过就直接忽略或者在消息处理前加一个去重表用唯一索引防重复插入。比重复更可怕的是消息丢失。消息丢失的高发点有三个一是生产者端发送非持久化消息Broker重启消息就没了重要消息必须设置PERSISTENT二是消费者在处理业务逻辑之前就自动确认了消息后面处理挂了消息也回不来这时就要改成手动确认三是用了非持久化的Topic普通订阅消费者不在线消息就丢了要改成持久化订阅。把这三个点守住消息丢失的概率能大幅下降。JMS还有一个重投递机制要知道消费者调用session.rollback()或者不确认消息Broker会重新投递但会有一个Redelivery策略默认会限制最大重投次数。重投次数耗尽之后消息会被放进死信队列。死信队列这个概念在生产环境里特别重要它相当于一个消息的“收容所”把多次处理失败的消息收集起来方便人工介入排查。ActiveMQ默认的死信队列名称是ActiveMQ.DLQ所有超限消息都会汇集到那里。5.3 生产调优的几个实用参数ActiveMQ的调优是很大的话题新手阶段掌握几个关键参数就够用了。首先是生产者端可以开启异步发送。ActiveMQ里可以在连接地址上加上useAsyncSendtrue参数让生产者不等待Broker的确认回执消息发送吞吐量会明显提升代价是一旦Broker挂了可能有少量消息未真正落盘就丢了。所以异步发送适合允许容忍极小概率消息丢失、但对吞吐量要求高的场景。我对这个参数的态度是非核心链路可以开核心链路必须考虑清楚。消费者端要注意prefetch的语义。prefetch表示一次拉取多少条消息到本地缓存默认值是1000。如果消费者处理每条消息比较慢prefetch太大会导致Broker把一堆消息发给消费者后消费者还没处理完就断开这些消息需要重新投递造成重复。可以把prefetch设为1让消费者一条条拉取这样能保证每条消息都处理完再取下一条损失一些吞吐量但换来回稳定。设置prefetch的方式也是在连接地址上加参数tcp://127.0.0.1:61616?jms.prefetchPolicy.queuePrefetch1。最后提醒一个容易忽略的点消息堆积不要只盯着消费者提升单机性能要看消费者的并发能力。如果Queue里的消息越堆越多单纯调大prefetch是治标不治本要检查是不是消费者数量不够。JMS规范里支持多个消费者竞争同一个Queue所以Java应用里可以开启多线程创建多个消费者或者部署多个实例让消息被并行消费。我在一个数据同步任务里刚开始单消费者每秒只能处理几百条后来开了4个消费者并行消费吞吐量直接翻了好几倍。记住消息队列本来就是用来并行的别把单个消费者当成唯一处理线程。5.4 给后来者的一份学习避坑清单最后按习惯总结几条干过的蠢事给准备学ActiveMQ和JMS的朋友抄作业第一概念没理清之前不要碰代码。先花半天时间把Queue、Topic、持久化、ACK这四件事想明白后面写代码会顺很多。第二环境变量和端口别凭感觉配置。ActiveMQ的61616和8161端口要背下来Broker地址写错是新手报错的第一大来源。第三写Demo的时候一定要打开管理控制台配合验证。发了消息看不到队列里有光盯着代码看是看不出所以然的。第四所有代码里的连接地址一律用failover协议不要给自己挖自动断线后不重连的坑。第五官方文档值得读。ActiveMQ官网有完整的JMS教程和API说明遇到问题优先查官方资料比搜索到的一堆互相矛盾的博客可靠。我在实际项目中还有一个习惯写JMS相关代码时把消息的生产、发送、消费日志都打上MessageID和业务ID串联起来排查问题的时候能顺着日志链路快速定位消息到底卡在哪一环。生产环境消息量大的时候没有日志链路排查消息问题就像在黑夜里找针这个习惯帮我省了无数排查时间。最后再分享一个小技巧ActiveMQ其实有个开箱即用的Java客户端命令行工具在bin目录下可以执行activemq browse来查看队列的消息内容配合activemq query能查询Broker状态。有时候代码还没写用命令行就能验证队列里消息来没来、长什么样对初学者来说是很直观的辅助工具。多花一点时间熟悉这些内置命令比反复重启应用去猜状态高效太多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑