ActiveMQ Artemis:解决通过选择器浏览消息成功但无法消费的问题

ActiveMQ Artemis:解决通过选择器浏览消息成功但无法消费的问题

本教程深入探讨了activemq artemis 2.18.0版本中一个特定且棘手的问题:当使用jms选择器可以成功浏览消息,但尝试通过messageconsumer接收同一条消息时却失败。文章揭示了该问题通常与openwire jms客户端协议以及artemis-3916缺陷有关,并提供了两种核心解决方案:切换至activemq artemis原生核心jms客户端,或将broker升级至2.25.0及以上版本,以确保消息的可靠消费。

ActiveMQ Artemis消息消费的困境

在ActiveMQ Artemis 2.18.0环境中,开发者有时会遇到一个令人困惑的现象:通过JMS选择器(例如,基于JMSMessageID)可以成功地使用QueueBrowser浏览队列中的特定消息,确认消息确实存在且选择器有效。然而,当随后使用MessageConsumer尝试通过相同的选择器接收这条消息时,receive()方法却可能返回null,甚至在某些实现中抛出IllegalStateException,表明无法获取到预期的消息。这种问题通常表现出间歇性,增加了诊断的难度。

以下是一个简化的问题代码结构,它展示了这种浏览成功但消费失败的场景:

import javax.jms.*;import java.util.Enumeration;public class ProblematicMessageConsumptionExample {    // 假设 activeMQJMSConnectionFactory 已经初始化,指向 Artemis Broker    private ConnectionFactory activeMQJMSConnectionFactory;     public void demonstrateProblem(String messageId) {        Connection connection = null;        Session session = null;        String selector = "JMSMessageID='" + messageId + "'";        try {            connection = activeMQJMSConnectionFactory.createConnection();            session = connection.createSession(true, Session.SESSION_TRANSACTED);            Queue deadQueue = session.createQueue("hospital");            connection.start();            // 步骤1: 浏览消息 - 预期成功找到一条消息            QueueBrowser browser = session.createBrowser(deadQueue, selector);            Enumeration e = browser.getEnumeration();            int foundedElements = 0;            while (e.hasMoreElements()) {                Message message = (Message) e.nextElement();                System.out.println("Browser found message with ID: " + message.getJMSMessageID());                foundedElements++;            }            browser.close();            if (foundedElements != 1) {                throw new IllegalStateException("Browser did not find exactly one message for selector: " + selector);            }            System.out.println("Browser successfully found " + foundedElements + " message(s).");            // 步骤2: 消费消息 - 在某些情况下,receive()会返回null,导致异常            MessageConsumer messageConsumer = session.createConsumer(deadQueue, selector);            Message received = messageConsumer.receive(1000); // 设置超时1秒            if (received == null) {                // *** 问题通常发生在这里:receive()返回null ***                throw new IllegalStateException("MessageConsumer.receive() returned null for selector: " + selector);            }            System.out.println("Consumer successfully received message with ID: " + received.getJMSMessageID());            messageConsumer.close();            session.commit(); // 提交事务            session.close();        } catch (Exception e) {            System.err.println("An error occurred during message processing: " + e.getMessage());            try {                if (session != null) {                    session.rollback(); // 回滚事务                    session.close();                }            } catch (JMSException e1) {                e1.printStackTrace();            }            throw new RuntimeException(e);        } finally {            if (connection != null) {                try {                    connection.close();                } catch (JMSException e) {                    throw new RuntimeException("Failed to close connection", e);                }            }        }    }}

问题根源:OpenWire客户端与ARTEMIS-3916

经过深入分析,该问题通常与客户端使用的JMS库及其底层协议密切相关。在ActiveMQ Artemis 2.18.0版本中,当客户端通过OpenWire JMS协议连接到Broker时,会触发一个已知的缺陷:ARTEMIS-3916

ARTEMIS-3916是一个特定于OpenWire协议的错误,它可能导致Broker在处理带有选择器的消息消费请求时出现内部逻辑问题,使得即使队列中存在匹配选择器的消息,MessageConsumer也无法正确地将其传递给客户端。这解释了为什么QueueBrowser能够“看到”消息(因为它只是查询消息元数据),而MessageConsumer却无法“获取”消息(因为它涉及更复杂的消费逻辑和消息锁定)。

值得注意的是,如果客户端使用的是ActiveMQ Artemis的原生核心JMS客户端协议,此问题通常不会发生,这进一步证实了问题在于OpenWire协议的兼容性层。

ONLYOFFICE ONLYOFFICE

用ONLYOFFICE管理你的网络私人办公室

ONLYOFFICE 1027 查看详情 ONLYOFFICE

解决方案

解决此问题主要有两种策略,它们分别从客户端和服务端入手:

方案一:确保使用ActiveMQ Artemis核心JMS客户端

这是推荐的首选方案。ActiveMQ Artemis拥有其专为高性能和稳定性设计的原生核心JMS客户端和协议。避免使用OpenWire协议可以绕过ARTEMIS-3916缺陷。

实现方法:

检查并调整Maven/Gradle依赖:确保您的项目依赖于ActiveMQ Artemis的官方JMS客户端库,例如 org.apache.activemq.artemis:artemis-jms-client 或 org.apache.activemq.artemis:artemis-jms-client-all。避免引入旧版Apache ActiveMQ的OpenWire客户端依赖(如org.apache.activemq:activemq-client),除非您确实需要与旧版ActiveMQ Broker兼容。

    org.apache.activemq.artemis    artemis-jms-client    2.18.0 <!--    org.apache.activemq.artemis    artemis-jms-client-all    2.18.0-->

使用ActiveMQ Artemis的ConnectionFactory:在代码中,确保您使用的是 org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory 来创建连接。该工厂默认使用Artemis的核心协议。

import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory;import javax.jms.*;import java.util.Enumeration;public class ArtemisCoreClientSolution {    private static final String BROKER_URL = "tcp://localhost:61616"; // Artemis Core Protocol 默认端口    public static void main(String[] args) throws Exception {        // 使用 ActiveMQJMSConnectionFactory 确保使用核心协议        ConnectionFactory connectionFactory = new ActiveMQJMSConnectionFactory(BROKER_URL);        try (Connection connection = connectionFactory.createConnection()) {            Session session = connection.createSession(true, Session.SESSION_TRANSACTED);            Queue testQueue = session.createQueue("hospital");            connection.start();            // 1. 发送一条消息用于测试            MessageProducer producer = session.createProducer(testQueue);            TextMessage sentMessage = session.createTextMessage("This is a test message for consumption.");            producer.send(sentMessage);            session.commit(); // 提交发送事务            System.out.println("Sent message with ID: " + sentMessage.getJMSMessageID());            String selector = "JMSMessageID='" + sentMessage.getJMSMessageID() + "'";            System.out.println("Using selector: " + selector);            // 2. 浏览消息            QueueBrowser browser = session.createBrowser(testQueue, selector);            Enumeration e = browser.getEnumeration();            int foundedElements = 0;            while (e.hasMoreElements()) {                Message msg = (Message) e.nextElement();                System.out.println("Browser found message: " + msg.getJMSMessageID());                foundedElements++;            }            browser.close();            if (foundedElements != 1) {                throw new IllegalStateException("Browser did not find exactly one message.");            }            System.out.println("Browser successfully found " + foundedElements + " message(s).");            // 3. 消费消息            MessageConsumer consumer = session.createConsumer(testQueue, selector);            Message receivedMessage = consumer.receive(5000); // 增加超时时间以确保有足够时间接收            if (receivedMessage == null) {                throw new IllegalStateException("MessageConsumer.receive() returned null unexpectedly!");            } else if (!(receivedMessage instanceof TextMessage) || !((TextMessage) receivedMessage).getText().equals(sentMessage.getText())) {                throw new IllegalStateException("Received message content mismatch.");            }            System.out.println("Consumer successfully received message with ID: " + receivedMessage.getJMSMessageID());            consumer.close();            session.commit(); // 提交接收事务            System.out.println("Message successfully browsed and consumed using Artemis Core Client.");        } catch (Exception e) {            System.err.println("An error occurred: " + e.getMessage());            throw e;        }    }}

方案二:升级ActiveMQ Artemis Broker

ARTEMIS-3916缺陷已在后续的ActiveMQ Artemis版本中得到修复。因此,升级Broker是解决此问题的最彻底方法。

以上就是ActiveMQ Artemis:解决通过选择器浏览消息成功但无法消费的问题的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/869895.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
ASML国内展出两款新型光刻机:不高于110nm、4倍生产效率
上一篇 2025年11月28日 04:34:03
sql中的and和or的优先级
下一篇 2025年11月28日 04:34:12

相关推荐

  • Java Random类如何生成随机数

    Random类位于java.util包,通过实例化生成伪随机数;无参构造以系统时间作种子,带参构造用固定种子可复现序列;提供nextInt()、nextDouble()等方法生成不同类型随机值;指定范围整数可用rand.nextInt(max-min)+min实现;多线程推荐ThreadLocalR…

    2026年9月21日
    100
  • VSCode怎么改环境_VSCode切换Python/Node等多版本环境教程

    切换VSCode环境需先安装对应语言扩展,再通过命令面板选择解释器或使用nvm切换Node版本,配合虚拟环境或launch.json配置确保运行和调试时使用正确版本,可通过终端命令验证环境,若失效可检查缓存、扩展冲突或权限问题。 VSCode改环境,其实就是让VSCode知道你想用哪个版本的Pyth…

    2026年9月21日
    000
  • 构建与调试PHP简易路由系统:从原理到实践

    本文将指导您如何从零开始构建一个基础的PHP路由系统,实现URL到控制器和方法的映射。我们将深入探讨$_SERVER[‘REQUEST_URI’]的解析、控制器文件的动态加载、方法调用以及如何通过.htaccess进行URL重写。同时,文章还将详细讲解常见的“未定义变量”错误…

    2026年9月21日
    100
  • windows10如何查看S.M.A.R.T.硬盘状态_windows10硬盘S.M.A.R.T.状态查看方法

    电脑运行慢、蓝屏或文件损坏可能是硬盘故障前兆,可通过S.M.A.R.T.技术检测健康状况。1、使用WMIC命令行工具输入“wmic diskdrive get model,status”查看状态,显示Pred Fail需立即备份数据;2、CrystalDiskInfo可深度分析S.M.A.R.T.参…

    2026年9月21日
    100
  • Photopea的AI功能怎么裁剪图片?快速实现高效图片裁剪技巧

    Photopea的AI功能怎么裁剪图片?快速实现高效图片裁剪技巧Photopea的AI功能怎么裁剪图片?快速实现高效图片裁剪技巧Photopea的AI功能怎么裁剪图片?快速实现高效图片裁剪技巧Photopea的AI功能怎么裁剪图片?快速实现高效图片裁剪技巧

    Photopea的AI功能通过智能选择工具与内容感知技术结合,实现高效图片裁剪。首先使用对象选择、快速选择或魔棒工具智能识别主体或背景,再通过“选择并遮住”精细调整边缘,尤其适用于复杂轮廓如发丝。随后可应用图层蒙版透明化背景,并用裁剪工具调整画布范围。结合内容感知填充可移除干扰元素并自动补全画面,内…

    2026年9月21日 用户投稿
    300
  • Sublime开发MySQL存储过程教程实战_封装重复逻辑减少前端负担

    Sublime开发MySQL存储过程教程实战_封装重复逻辑减少前端负担Sublime开发MySQL存储过程教程实战_封装重复逻辑减少前端负担Sublime开发MySQL存储过程教程实战_封装重复逻辑减少前端负担Sublime开发MySQL存储过程教程实战_封装重复逻辑减少前端负担

    在web开发中使用mysql存储过程能有效封装逻辑并减少前端负担,本文介绍了其优势、环境配置及实战技巧。一、存储过程的优势包括减少网络传输、提高性能、统一业务逻辑;二、sublime text配置步骤为安装package control、sublimerepl插件、sql语法高亮插件,并建议新建.s…

    2026年9月21日 用户投稿
    800
  • PHP框架中间件有什么用处_PHP框架中间件设计与实现

    PHP框架中间件是处理请求和响应的过滤器,用于实现身份验证、日志记录、CORS等通用逻辑,核心价值在于解耦和提升可维护性。通过定义中间件接口、具体中间件类及管道调度器可实现自定义中间件,如身份验证或CORS处理。在Laravel中可通过Kernel.php配置全局、分组或路由级中间件,执行顺序按注册…

    2026年9月21日
    000
  • Java中字符到数字转换:解决for循环提前返回的常见陷阱

    本文探讨java中`for`循环在字符到数字转换时,因`return`语句放置不当导致程序提前终止、无法完整处理字符串的问题。我们将分析这种常见陷阱,并提供修正方案,演示如何正确利用循环填充数组,并在循环结束后统一返回最终结果,确保每个字符都能被准确映射和组合。 引言:字符到数字的映射需求 在编程实…

    2026年9月21日
    000
  • 梦幻号虚拟主播电商运营宝典(附新手教程+配套工具清单)

    虚拟主播电商的核心在于“内容驱动销售,人设凝聚用户”,要让“梦幻号”真正动起来并实现带货,必须先赋予其鲜明的人设,包括清晰的定位标签(如美食家、科技宅)、独特的人格魅力(性格、口头禅、小缺点)和与产品的强关联性,使其具备辨识度和故事感,从而建立用户信任;接着通过obs studio、vtube st…

    2026年9月21日
    000
  • 软删除(Soft Delete)的实现与恢复逻辑

    使用软删除的原因是它允许数据恢复和保持数据完整性。1) 软删除通过标记数据为已删除而非实际删除,提供了数据恢复的可能性。2) 它保持数据的历史记录,确保数据完整性。实现软删除通常在数据库中添加字段如is_deleted或deleted_at,恢复数据时重置这些字段。 软删除(Soft Delete)…

    2026年9月21日
    000
  • deepseek下载速度优化_从deepseek下载速度优化官网获取

    deepseek下载速度优化入口在官网https://www.deepseek.com,进入后可通过设置调整响应模式、使用智能路由和数据压缩技术提升速度。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜ deepseek下载速度优化入口地址在…

    2026年9月21日
    000
  • Linux如何设置目录的执行权限

    目录的执行权限是访问其内容的“钥匙”,使用chmod命令可通过符号或八进制模式设置,常见权限为755(所有者rwx,组和其他用户rx),递归设置时推荐结合find命令分别处理文件和目录,避免误加执行权限。 在Linux中,设置目录的执行权限( x )并非意味着你可以“运行”这个目录,而是赋予了你进入…

    2026年9月21日
    000
  • Java多线程API调用中Future.get()返回null的解决方案

    本文旨在解决%ignore_a_1%api调用中`future.get()`方法返回`null`的常见问题。当使用`callable`和`executorservice`并发执行api请求并尝试获取结果时,如果流读取逻辑不当,可能导致获取到的数据为空。文章将详细解释问题根源,并提供使用`string…

    2026年9月21日
    000
  • 升级后如何检查兼容性

    检查兼容性是升级后确保系统稳定的关键,需先确认硬件配置与驱动支持,再验证软件运行及业务流程正常,最后通过系统日志排查潜在错误,逐步排除风险。 系统或软件升级后,检查兼容性是确保各项功能正常运行的关键步骤。直接进入实际使用前,花时间验证兼容性可以避免数据丢失、服务中断等问题。 检查硬件和驱动支持 某些…

    2026年9月21日
    000
  • 小红书零基础赚钱攻略(精准选题+涨粉秘籍+账号运营+高转化变现方法)

    找到自己真正擅长或有热情的领域,结合用户需求和竞争情况确定细分赛道;2. 通过优质内容、高互动数据、精准关键词和话题标签提升曝光;3. 利用品牌合作、带货佣金、知识付费等方式实现变现,核心是建立在信任基础上的持续价值输出,最终将流量转化为实际收益。 小红书零基础赚钱,核心在于找到自己的定位,持续输出…

    2026年9月21日
    000
  • mysql如何排查排序异常

    排查MySQL排序异常需先确认ORDER BY是否生效,检查子查询、UNION及应用层逻辑是否覆盖排序;通过EXPLAIN分析是否使用索引排序,避免Using filesort;确保字段类型、字符集和排序规则(collation)符合预期,处理NULL值和大小写敏感性;关注sort_buffer_s…

    2026年9月21日
    000
  • 即梦AI运镜控制怎么控制_即梦AI视频镜头移动技巧详解

    掌握即梦AI运镜需四步:一、用“镜头缓慢推进”等预设提示词生成标准运动;二、通过动效画板框选主体并绘制运动路径;三、设置首尾帧引导转场,实现穿越或循环效果;四、结合“希区柯克式变焦”“时间冻结环绕”等高级技巧增强视觉表现。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 Dee…

    2026年9月21日
    000
  • .com网站安全维护_保障.com网站稳定的措施

    答案:保障.com网站稳定需加强安全防护、定期备份、实时监控和应急准备。部署防火墙、更新系统、使用HTTPS、限制端口;制定自动备份并异地存储,定期恢复测试;利用监控工具检测可用性与异常流量,优化加载速度;建立应急流程,严格权限管理,定期演练。细节执行到位才能确保长期安全稳定运行。 确保.com网站…

    2026年9月21日
    100
  • 三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式

    三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式

    随着消费理念升级与需求日益多样化,电视已不再仅仅是观看节目和影音娱乐的工具,而是逐渐演变为承载家居美学、传递情感温度、连接智慧生活的艺术载体。在这一变革浪潮中,三星率先引领艺术电视领域的创新风向,theframe画壁艺术电视与theserif画境艺术电视成功打破科技与艺术之间的界限,将电视升华为可观…

    2026年9月21日 用户投稿
    100
  • 分布式锁(Redis)解决数据竞争

    使用redis实现分布式锁来解决数据竞争可以通过setnx和expire命令。1)使用setnx尝试获取锁,并通过expire设置锁的过期时间防止死锁。2)释放锁时使用watch命令确保锁未被其他客户端获取。需要注意redis的单点故障、高并发性能瓶颈和锁的过期时间设置。 在处理高并发的应用场景中,…

    2026年9月21日
    000

发表回复

登录后才能评论
关注微信