当前位置: 首页 > 知识库问答 >
问题:

即使activemq中的队列不为空,JMS实现中的receiveNoWait也会返回null

苏宾鸿
2023-03-14

我试图在我的项目中实现JMS。我使用活动mq作为提供者,并使用持久队列。下面是从活动mq中检索元素的代码

            conn = GlobalConfiguration.getJMSConnectionFactory().createConnection();
            conn.start();
            session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageConsumer consumer = session.createConsumer(queue);
            ObjectMessage obj = (ObjectMessage) consumer.receiveNoWait();

这段代码有时会返回数据,有时会返回null,即使我可以在活动的mq管理控制台中将待处理消息的数量视为非零。我读了很多文章,很少有人提到JMS api没有强制您每次都要获取元素,并且您必须相应地编码。因为在我的场景中,我依赖于队列,一旦队列返回null,我就会杀死进程,所以我通过以下方式修改了代码

我没有调用receiveNoWait,而是在通过队列浏览器检查队列中是否存在元素后开始使用receive。以下是修改后的代码

public static <T> T retrieveObjectFromQueue(Queue queue, Class<T> clazz) {
synchronized (queue) {
    if(!queueHasMoreElements(queue))
        return null;
    Connection conn = null;
    Session session = null;
    try {
        conn = GlobalConfiguration.getJMSConnectionFactory().createConnection();
        conn.start();
        session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageConsumer consumer = session.createConsumer(queue);
        ObjectMessage obj = (ObjectMessage) consumer.receive();
        return clazz.cast(obj.getObject());
    } catch(Exception e) {
        throw new RuntimeException(e);
    }finally {
        closeSessionAndConnection(session, conn);
    }
}


public static boolean queueHasMoreElements(Queue queue) {
Connection conn = null;
Session session = null;
try {
    conn = GlobalConfiguration.getJMSConnectionFactory().createConnection();
    conn.start();
    session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
    QueueBrowser browser = session.createBrowser(queue);
    Enumeration enumeration = browser.getEnumeration();
    return enumeration.hasMoreElements();
} catch(Exception e) {
    throw new RuntimeException(e);
}finally {
    closeSessionAndConnection(session, conn);
}

现在,我的代码在处理了大约20-30个元素后被卡住了,我可以在管理控制台中再次看到挂起的元素。当我尝试使用调试模式时,我意识到,在检索20-30个元素之后,我的代码会在消费者处卡住。receive(),在队列为空的情况下是应该的,但当我检查管理控制台时,它显示了队列中的许多元素。

我使用jdbc(mysql)作为Activemq的持久存储。我使用的配置xml在Activemq配置示例中给出(Activemq/实例/conf/activemq-jdbc-performance.xml)

我正在使用tcp://localhost:61616?jms.prefetchPolicy.queuePrefetch=1作为activemq url。

请让我知道我做错了什么。我使用的是java8和apache activeMq 5.13.1

谢谢

共有2个答案

辛龙野
2023-03-14

我们看到了一个类似的问题(其中< code>receiveNoWait返回null,即使代理上有消息)。我认为这是由于activemq [1][2]中的预取缓冲区,这可以通过将预取极限设置为0来修复。

[1]https://ActiveMQ . Apache . org/what-is-the-prefetch-limit-for < br >[2]当消息可用时,JMS receiveNoWait()是否保证消息传递?

范楚
2023-03-14

JMS规范也没有强制队列浏览器返回队列中的所有消息,您可能只能在它开始时获得那里的快照,这取决于许多因素。

您试图将它无法保证的语义强加给 JMS。您可以尝试将预取设置为零,这将导致客户端轮询代理以获取消息,并等待代理告诉存在或没有消息。但是,如果在轮询时消息尚未到达队列,您可能仍然一无所获,这只是您需要处理的事情。

您还可以使用定时接收方法,并施加一个超时,您愿意在返回和终止应用程序之前等待该超时。

 类似资料:
  • 因此,我使用Spring integration链接JMS和ActiveMQ,如下所示:- 如何使其工作,以便发送到此队列并从中接收消息?请帮忙。

  • 问题内容: 我只是对JMS和Apache ActiveMQ有所了解。并且想知道这里的人们将JMS或类似的消息队列技术用于什么吗? 问题答案: JMS(ActiveMQ是JMS代理实现)可以用作允许异步请求处理的机制。您可能希望执行此操作,因为请求需要很长时间才能完成,或者因为实际的请求可能涉及多个方面。使用它的另一个原因是允许多个客户端(可能以不同的语言编写)通过JMS访问信息。ActiveMQ是

  • 我们在ActiveMQ Artemis中面临一个问题。其中一个队列在达到最大内存设置-时进入分页状态。经过一段时间后,当用户处理它时,消息数量会减少很多。但直到队列为空,它才恢复分页状态。是预期的行为吗?

  • 我正在收听一个Activemq队列。 我的配置如下: 从控制台日志中,我可以看到尝试重新连接到该服务器。 [2014-08-20 08:57:43,303]INFO 236[ActiveMQ Task-1]-org.apache.activemq.transport.failover.FailoverTransport.doReconnect(FailoverTransport.java:1030

  • 假设我收集了以下文档: 所有文档都将始终有“水果”字段 某些文档可能没有“attributes”数组 对于属性数组中包含元素的文档,它可以是1到20个元素 我需要根据属性返回这个。数量介于4和8之间 > 即使属性字段缺失或数量标准不匹配,也始终显示id和水果 在属性数组中最多只显示2个符合搜索条件的元素,按数量降序排序 {_id:1,水果:苹果,属性:[{颜色:红色,大小:小,数量:5}]}, {

  • 我们有一个场景,在捕获异常之后,我们使用Mule(我知道是3.4版——旧版)回滚JMS事务。ActiveMQ应该在提交事务之前将消息保留在队列上(以使其持久化),或者在Mule启动回滚后,根据回滚设置重新传递消息。 然而,似乎在回滚之后,消息不会被重新传递,而是位于队列连接上“阻止”进一步的消息。就好像没有收到回滚消息一样。有人知道为什么不退还吗? 从日志中提取: