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

使用临时队列超时读取的JMS同步请求/应答

燕靖
2023-03-14

2.)ProgramB有一个监听器来监听从ProgramA创建的消息,处理消息并回复它。但是ProgramB需要与第三方web服务通信,有时需要超过10秒才能回复,这就是我设置消费者监听5000秒(5s)的问题,当然之后会超时。所以消息不会被接收。

我的观察:1.)即使ProgramA完成了读取(还没有回复,在那一刻我试图删除临时队列),但它不能这样做,ProgramB仍然可以写到回复队列,但没有人会读到那个消息(太晚了)。

当我尝试将5s的监听时间改为20s时,问题就解决了,但这是正确的方法吗?

部分代码:

Destination replyQueue = send(jmsUtil, actionDTO);
SalesOrderResponseDTO responseDTO = readReply(jmsUtil, replyQueue, actionDTO);

public Destination send(JmsSessionUtil jmsUtil, SalesOrderActionDTO soDTO) {
    try {
        utx.begin();        
        jmsUtil.send(soDTO, null, 0L, 1, Long.parseLong(configBean.getProperty("jms.payrequest.timetolive")), true);
        utx.commit();
        return jmsUtil.getReplyQueue();
    } catch (Exception e) {
        try {
            utx.rollback();
        } catch (Exception e1) {

        }       
    }
    return null;
}

public SalesOrderResponseDTO readReply(JmsSessionUtil jmsUtil, Destination replyQueue, SalesOrderActionDTO actionDTO) {
    SalesOrderResponseDTO responseDTO = null;
    try {       
        utx.begin();

        responseDTO = (SalesOrderResponseDTO) jmsUtil.read(replyQueue);

        if (responseDTO != null) {
            // fires the response event
            SalesOrderResponsePayload eventPayload = new SalesOrderResponsePayload();
            eventPayload.setResponseDTO(responseDTO);
            responseEvent.fire(eventPayload);
        } else { // timeout
            ((TemporaryQueue) replyQueue).delete();
            jmsUtil.dispose();
        }
        utx.commit();
        return responseDTO;
    } catch (Exception e) {
        try {
            utx.rollback();
        } catch (Exception e1) {
        }
    }
    return responseDTO;
}

public String send(MessageDTO messageDTO,
            JMSQueueEnum resultNotificationQueue, Long parentProcessId,
            int JMSPriority, long timeToLive, boolean hasReply)
            throws JMSException, InvalidDTOException, NamingException {

    try {
        // Process optional parameters
        messageDTO.setResultNotificationQueue(resultNotificationQueue);
        messageDTO.setParentProcessId(parentProcessId);

        // Wrap MessageDTO in a JMS ObjectMessage
        ObjectMessage msg = MessageDTOHelper.serialize(session, messageDTO);
        msg.setJMSType(messageDTO.getClass().getSimpleName());
        msg.setStringProperty("DTOType", messageDTO.getClass()
                .getSimpleName());

        requestProducer = session.createProducer(queue);

        if (hasReply) {
            replyQueue = session.createTemporaryQueue();
            replyConsumer = session.createConsumer(replyQueue);     
            msg.setJMSReplyTo(replyQueue);
        }

        if (JMSPriority > -1) {
            requestProducer.send(msg, DeliveryMode.PERSISTENT, JMSPriority,
                    timeToLive);
        } else {
            // Send the JMS message
            requestProducer.send(msg);
        }
        return msg.getJMSMessageID();
    } catch (Exception e) {

    }

    return null;
}

public MessageDTO read(Destination replyQueue) throws JMSException,
            NamingException {
    if (replyQueue instanceof Queue) {
        Message msg = replyConsumer.receive(20000);

        if (msg == null) {
            return null;
        }

        MessageDTO messageDTO = MessageDTOHelper
                .deserialize((ObjectMessage) msg);

        return messageDTO;
    } else {

    }
    return null;
}

共有1个答案

鱼宜
2023-03-14

这里的实际问题是您需要同步还是异步通信。

我总是更喜欢异步,从您的问题来看,在您的情况下似乎也不需要同步通信。但是,如果有同步的原因,那么您将被临时队列所困扰--您将不得不指定超时间隔,并且您将面临问题中表达的问题。如果程序A可以等待,则提高超时间隔,尽管这远不是最优的。据我所知,程序B不可能检查A是否还在收听。

在异步通信的情况下,您有(至少)两个JMS选项:

    null
    null
 类似资料:
  • 问题内容: 如果我们通过“临时队列”使用JMS请求/答复机制,那么该代码是否可伸缩? 截至目前,我们尚不知道每秒将支持100个请求,还是每秒支持1000个请求。 下面的代码是我正在考虑实现的代码。它以“同步”方式使用JMS。关键部分是创建“消费者”的位置,以指向为此会话创建的“临时队列”。我只是不知道使用这样的临时队列是否是可扩展的设计。 更新: 我遇到了另一种模式,请参阅此博客。 该想法是对发送

  • 我有以下设置: 外部应用程序写入到jms队列 jms队列也是外部的,所以这里不可能进行配置 运行在Glassfish上的现有应用程序,使用ActiveMQ将服务器连接到jms队列 现有的应用程序是一个MessageDriven bean,实现了MessageListener接口(当消息放在队列中时,当前正在处理消息) 新的要求是消息只能在02:00到04:00的时间段内处理 如何最好地限制Mess

  • 我在Weblogic 12c上部署了一个MDB,它从JMS队列(UDQ)读取消息。MDB正在读取消息,但它没有从JMS队列中删除,这导致消息被重复读取。所以,我想知道MDB何时确认JMS队列它成功读取了消息,并且队列应该删除该消息。

  • 我有一个网络应用程序,当用户提交请求时,我们向远程服务发送JMS消息,然后等待回复。(也有异步请求,我们为消息重放等设置了各种细节,所以我们更愿意坚持使用JMS而不是HTTP) 在如何使用JMS实现请求-响应?,ActiveMQ似乎不鼓励每个请求使用临时队列,也不鼓励在JMSCorrelationID上使用选择器的临时消费者,因为这会增加开销。 但是,如果我使用池消费者进行回复,我如何从回复消费者

  • 我通过命名的JMS队列将JMS请求发送到Weblogic 10.3服务器,并通过临时队列接收回复。 客户(裸体): 服务器MDB(消息驱动bean): 问题是第一个服务器回复经常丢失!也就是说,每4-5个回复都以超时结束。当消费者收到第一个答案时,它将继续收到所有剩余的答案,所以问题只出在临时队列创建后通过临时队列发送的第一条消息上。 我的问题是:我是否必须为临时队列设置一些特殊的设置,以便它在创

  • 我有Weblogic 12.1.2和IBM WebSphere MQ Explorer 7.5.0.2。 在Weblogic中,我创建了: JMS服务器 我有一个JAVA程序,可以向这个队列发送消息。 我想使用MQ Explorer来读取来自此队列的消息。我如何设置它?我应该在MQ Explorer中做什么和如何设置,以连接到此队列?有人能给我一个Web链接吗?我找不到任何有用的东西,但也许我想错

  • 问题内容: 我有一个 要求: 我想知道默认的超时时间是多少?以及如何将其设置为3秒或不定秒的特定值? 问题答案: 它没有指定的默认值。该规范根本没有讨论超时。 通常,您可以为承诺实现自己的超时包装器: 如https://github.com/github/fetch/issues/175中所述 (https://github.com/mislav)

  • 我有一个java客户机,它在队列中发送jms消息(“队列请求”)。该消息包含一个int属性(“id”),其中包含唯一的客户端id号。消息正在处理中,然后进入另一个队列(“队列响应”)。如何让客户机等到具有其id的消息在队列中,然后读取它。我曾尝试使用侦听器并实现onMessage,但当收到消息时,我如何停止侦听?