Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果在使用消息后出现任何错误,如何在JMS消息队列中保存消息?_Java_Jms_Message Queue_Middleware - Fatal编程技术网

Java 如果在使用消息后出现任何错误,如何在JMS消息队列中保存消息?

Java 如果在使用消息后出现任何错误,如何在JMS消息队列中保存消息?,java,jms,message-queue,middleware,Java,Jms,Message Queue,Middleware,我的场景是-我将消息发布到队列中,一旦消息被使用,我就将其发送到第三方中间件应用程序。如果那个中间件应用程序关闭了,那么我发布的消息就不见了。我不希望在中间件应用程序关闭时丢失该消息,而是希望它处于等待状态或在队列中等待。请提出建议,如何处理这种情况?尽管目前还不清楚您的应用程序是如何设计的,但我建议您修改消费者应用程序以使用本地事务中的消息,并将消息发布到第三方中间件应用程序。如果post成功,那么您可以提交将从JMS队列中删除消息的事务。若您的应用程序无法发布消息,您可以简单地回滚事务,这将

我的场景是-我将消息发布到队列中,一旦消息被使用,我就将其发送到第三方中间件应用程序。如果那个中间件应用程序关闭了,那么我发布的消息就不见了。我不希望在中间件应用程序关闭时丢失该消息,而是希望它处于等待状态或在队列中等待。请提出建议,如何处理这种情况?

尽管目前还不清楚您的应用程序是如何设计的,但我建议您修改消费者应用程序以使用本地事务中的消息,并将消息发布到第三方中间件应用程序。如果post成功,那么您可以提交将从JMS队列中删除消息的事务。若您的应用程序无法发布消息,您可以简单地回滚事务,这将使消息重新出现在JMS队列中。该消息将再次发送。

您应该创建如下会话:

Session session = connection.createSession(false,
                       Session.CLIENT_ACKNOWLEDGE);
当您尝试将邮件发送到第三方应用程序时:

  • 如果它起作用,你应该确认消息

  • 如果它关闭了,您不应该对其进行确认,这样JMS提供程序将能够重新传递它,并且消息不会丢失<代码>消息。确认()


另外,您可以查看以下内容:

这可以通过使用会话确认来实现。为此,请首先修改生产者代码以使用Session.AUTO\u ACKNOWLEDGE。创建队列会话时,将自动确认设置为false。这意味着消费者必须承认。当消费者发送消息确认时,消息将从队列中删除,否则它将保留在队列中

try {
        QueueConnectionFactory qcf = getQueueConnectionFactory(); 
        Queue q = getDestination();
        QueueConnection qConnection = qcf.createQueueConnection();
        QueueSession qSession = qConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

        QueueReceiver qReceiver = qSession.createReceiver(q);

        qConnection.start();
        Message msg = qReceiver.receive();

  // here send your message to third party application 
  //if your third party application is down 
        if(thirdpartyapp is down){
          //here you can raise an exception 
          //or just do nothing 
          // you're not sending acknowledgement here so the msg will 
           //remain in the queue
        }else{      
          msg.acknowledge();//here youre sending ack, so msg will be deleted
          qReceiver.close();
          qConnection.close();
        }

    } catch (JMSException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
下面是生产商代码

try {
        QueueConnectionFactory qcf = AppUtils.getQueueConnectionFactory(); 
        Queue q = AppUtils.getDestination();
        QueueConnection qConnection = qcf.createQueueConnection();
        QueueSession qSession = qConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

        QueueSender qSender = qSession.createSender(q);

        qConnection.start();
        TextMessage msg = qSession.createTextMessage("Hello");
        qSender.send(msg);

        qSender.close();
        qConnection.close();

    } catch (JMSException e) {
        // log your error to log file
        e.printStackTrace();
    }
在消费者端,您必须做同样的事情,创建一个队列会话,将AUTO_ACKNOWLEDGE设置为false

处理邮件后,您可以发送确认以从队列中删除邮件,否则邮件将保留在队列中

try {
        QueueConnectionFactory qcf = getQueueConnectionFactory(); 
        Queue q = getDestination();
        QueueConnection qConnection = qcf.createQueueConnection();
        QueueSession qSession = qConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

        QueueReceiver qReceiver = qSession.createReceiver(q);

        qConnection.start();
        Message msg = qReceiver.receive();

  // here send your message to third party application 
  //if your third party application is down 
        if(thirdpartyapp is down){
          //here you can raise an exception 
          //or just do nothing 
          // you're not sending acknowledgement here so the msg will 
           //remain in the queue
        }else{      
          msg.acknowledge();//here youre sending ack, so msg will be deleted
          qReceiver.close();
          qConnection.close();
        }

    } catch (JMSException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

JMS队列不是消息存储

如果您有一条“坏消息”,处理继续失败,那么JMS服务器(如果配置)将不可避免地将该消息转储到一个“死消息队列”,该队列将慢慢填满,直到另一个进程将其耗尽

您不希望将坏消息保留在队列中,因为它们可能会阻塞队列(假设您有10个消费者,前10条消息都是坏消息,因此所有进程所做的就是继续处理坏消息——使队列暂停)

因此,您需要某种机制来将消息存储到异常接收器中,然后将它们注入到主队列中进行处理


死消息队列不是这种机制(不要将消息存储在JMS队列中),相反,它可以是一种将异常消息路由到更永久的存储区域(即db表或其他东西)的机制

一旦到了那里,他们可以被审查(自动,手动,无论什么),或者重新交付或取消


但关键的一点是,您需要一个外部机制来实现这一点,JMS服务器本身并不是此类消息的合适场所。

您的持久消息-->第三方如何?第三方的ack系统是什么?i、 e.你怎么知道他们是不是站起来了,即使他们站起来了,他们也没有出错并扔掉你的味精--你们和第三方有什么合同?我正在使用RESTfulWeb服务合同与第三方应用程序交互。如果服务器关闭,它将尝试连接几次,然后如果失败或连接丢失,我们将收到错误消息。您是否可以设置死信队列,然后定期将这些消息移回主队列?“不要将消息存储在JMS队列中”您能进一步解释这一点吗?队列可以是持久的,那么为什么不存储在其中呢?在某些情况下,您需要按照严格的顺序处理消息。在这种情况下,只要错误消息没有被成功消费,它们就会被保留在队列中。您能否给出一个代码示例,说明您可以实现上述功能?