为什么 JMS 确认模式不能在 ibm mq 中正常工作?
Why does JMS acknowledge mode not work in wildly with ibm mq?
我想在通过 JMS 从 ibm 队列传递消息时使用确认模式。
所以,我这样配置上下文:
private JMSContext createJmsContext() throws JMSException {
JmsConnectionFactory cf;
JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
cf = ff.createConnectionFactory();
cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, props.getProperty(Q_HOST));
cf.setIntProperty(WMQConstants.WMQ_PORT, Integer.valueOf(props.getProperty(Q_PORT)));
cf.setStringProperty(WMQConstants.WMQ_CHANNEL, props.getProperty(Q_CHANNEL));
cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, props.getProperty(Q_MANAGER));
cf.setStringProperty(WMQConstants.WMQ_APPLICATIONNAME, "JmsPutGet (JMS)");
cf.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, true);
cf.setIntProperty(WMQConstants.ACKNOWLEDGE_MODE, WMQConstants.CLIENT_ACKNOWLEDGE);
return cf.createContext();
}
这里是特殊参数:
cf.setIntProperty(WMQConstants.ACKNOWLEDGE_MODE, WMQConstants.CLIENT_ACKNOWLEDGE);
在代码逻辑中,我使用处理消息的消息侦听器:
consumer.setMessageListener(message -> {
try {
// business logic
message.acknowledge();
} catch (Throwable e) {
try {
// saving unsuccessful message to special database
} catch (Throwable e) {
// if database does not work, we want message to return back to queue and try process it again when database will work
sleep(60_000); // to prevent too many process requests, there is only one working thread, so we can pause it
}
}
});
现在这段代码不起作用:如果数据库出现故障,消息将丢失。我们无法通过 JMS 浏览找到它。为什么?
您在创建上下文时没有使用 sessionMode 参数。据我所知,在未指定 sessionMode
的情况下创建的上下文与 AUTO_ACKNOWLEDGE
相同,其中 JMS 客户端将在消息传递到应用程序后自动确认消息。因此,对于您的情况,您需要使用:
cf.createContext(JMSContext.CLIENT_ACKNOWLEDGE);
我试过了,它对我有用,这意味着如果 message.acknowlege()
没有被调用,同样的消息会再次发送。
我想在通过 JMS 从 ibm 队列传递消息时使用确认模式。
所以,我这样配置上下文:
private JMSContext createJmsContext() throws JMSException {
JmsConnectionFactory cf;
JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
cf = ff.createConnectionFactory();
cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, props.getProperty(Q_HOST));
cf.setIntProperty(WMQConstants.WMQ_PORT, Integer.valueOf(props.getProperty(Q_PORT)));
cf.setStringProperty(WMQConstants.WMQ_CHANNEL, props.getProperty(Q_CHANNEL));
cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, props.getProperty(Q_MANAGER));
cf.setStringProperty(WMQConstants.WMQ_APPLICATIONNAME, "JmsPutGet (JMS)");
cf.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, true);
cf.setIntProperty(WMQConstants.ACKNOWLEDGE_MODE, WMQConstants.CLIENT_ACKNOWLEDGE);
return cf.createContext();
}
这里是特殊参数:
cf.setIntProperty(WMQConstants.ACKNOWLEDGE_MODE, WMQConstants.CLIENT_ACKNOWLEDGE);
在代码逻辑中,我使用处理消息的消息侦听器:
consumer.setMessageListener(message -> {
try {
// business logic
message.acknowledge();
} catch (Throwable e) {
try {
// saving unsuccessful message to special database
} catch (Throwable e) {
// if database does not work, we want message to return back to queue and try process it again when database will work
sleep(60_000); // to prevent too many process requests, there is only one working thread, so we can pause it
}
}
});
现在这段代码不起作用:如果数据库出现故障,消息将丢失。我们无法通过 JMS 浏览找到它。为什么?
您在创建上下文时没有使用 sessionMode 参数。据我所知,在未指定 sessionMode
的情况下创建的上下文与 AUTO_ACKNOWLEDGE
相同,其中 JMS 客户端将在消息传递到应用程序后自动确认消息。因此,对于您的情况,您需要使用:
cf.createContext(JMSContext.CLIENT_ACKNOWLEDGE);
我试过了,它对我有用,这意味着如果 message.acknowlege()
没有被调用,同样的消息会再次发送。