【问题标题】:How to stop getting messages deleted without acknowledgement in Oracle AQ?如何在 Oracle AQ 中停止在未确认的情况下删除消息?
【发布时间】:2020-02-24 09:09:22
【问题描述】:

我已经设置了一个客户 Oracle AQ。我在具有CLIENT_ACKNOWLEDGE 模式的Java Web 应用程序中观察来自此队列的消息。但是,一旦我收到onMessage 方法中的消息,这些消息似乎就会从 Oracle 队列中删除。我的假设是,除非我在客户端 acknowledge 他们,否则不应删除该消息。我该如何阻止这个?

Oracle 队列架构如下所示:

BEGIN DBMS_AQADM.CREATE_QUEUE_TABLE(
  Queue_table => '"TESTUSER"."myqueuetable"', 
  Queue_payload_type => 'TESTUSER.messageobject', 
  multiple_consumers => false
);
END;
/

BEGIN DBMS_AQADM.CREATE_QUEUE(
  Queue_name => 'TESTUSER.myqueue', 
  Queue_table => 'TESTUSER.myqueuetable', 
  Queue_type => 0, Max_retries => 5, Retry_delay => 0
);
END;
/

BEGIN dbms_aqadm.start_queue (
  queue_name => 'testuser.myqueue'
);
END;

我像这样观察我的 Java 应用程序中的消息

 //somewhere in my app
session = queueConnection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
queueReceiver = ((AQjmsSession) databaseConnectionManager.getSession())
 .createReceiver(databaseConnectionManager.getQueue(), Messageobject.getORADataFactory());
queueReceiver.setMessageListener(this);


//in my listener class
@Override
public void onMessage(Message message) {
 AdtMessage msg = (AdtMessage) message;

 try {
  Messageobject message = (Messageobject) msg.getAdtPayload();

  if (isUserConnected(message.userId)) {
   logger.debug("Message acknowledged");
   msg.acknowledge();
   //handle the message. the message should be deleted now.
  } else {
   //i don't want the message to be deleted
  }

 } catch (JMSException | IllegalArgumentException | SQLException e) {
  logger.error("An error occurred while sending an outgoing blob", e);
 }
}

【问题讨论】:

  • 我不知道 Oracle AQ,但我同意不应删除该消息。但是它可能会落在其他队列中 - Oracle AQ 中是否存在“死信队列”的概念?另外,我建议更改您的程序以使用事务会话 .createQueueSession(true,... 并在出现错误时回滚。这应该更安全,绝对不会删除您的消息。
  • 回滚有一些不良影响。会话似乎再次收到消息 - 即使它们是在会话回滚之前传递的。
  • Oracle 提供的帮助很少。我现在已经创建了一个普通的表。
  • 你正在创建一个单一的消费者队列,一旦成功消费,消息就会被删除。要保留消息,请将保留时间设置为大于零的值。参考docs.oracle.com/database/121/ARPLS/d_aqadm.htm#ARPLS109

标签: java oracle jms jax-ws oracle-aq


【解决方案1】:

您正在创建一个单一的消费者队列,一旦成功消费该消息就会被删除。

要保留消息,请在创建队列时将保留时间设置为大于零的值。

BEGIN 
  DBMS_AQADM.CREATE_QUEUE(
    Queue_name => 'TESTUSER.myqueue', 
    Queue_table => 'TESTUSER.myqueuetable', 
    Queue_type => 0, Max_retries => 5, Retry_delay => 0,
    retention_time => 300    -- retain for next 5 minutes
  );
END;
/

参考https://docs.oracle.com/database/121/ARPLS/d_aqadm.htm#ARPLS109

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 2021-10-19
    • 2021-05-25
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 2017-03-25
    相关资源
    最近更新 更多