我无法处理来自IBM MQ的大型消息,并得到以下错误:
JMSCMQ0001:WebSphere MQ调用失败,原因为"2080"("MQRC_TRUNCATED_MSG_failed")
我使用的是DefaultListenerContainer,而不是直接使用IBM MQ Java API类通过MessageConsumer消费。我相信,通过使用IBM MQ JMS API,您可以在从队列中检索消息之前指定选项。但是,我如何使用DefaultListenerContainer做到这一点,是否有可以为这些设置的系统属性?
如果使用IBM MQ JMS API(我不使用这样的消息,粘贴只是为了参考):
MQGetMessageOptions MQGetMessageOptions=新的MQGetMessageOptions();mqGetMessageOptions.waitInterval=ipreoProperties.getMqReceiveWaitTime();mqGetMessageOptions.options=MQC.MQGMO_WAIT|MQC.MQPMO_SYNCPOINT|MQC.MQGMO_ACCEPT_RUNCATED_MSG;
下面是我的IBM MQ连接的Java配置:
@Bean
public CachingConnectionFactory ipreoMQCachingConnectionFactory() {
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
//Not defining MQQueueConnectionFactory as separate bean as Spring boot's auto-configuration finds two instances
//of ConnectionFactory and throws ambiguous implementation exception
//One implementation is CachingConnectionFactory and other one would be MQQueueConnectionFactory if defined separately
MQQueueConnectionFactory mqConnectionFactory = new MQQueueConnectionFactory();
try {
mqConnectionFactory.setHostName(env.getRequiredProperty(AppEnvPropertyConstants.JmsConstants.IPREO_MQ_HOSTNAME));
mqConnectionFactory.setQueueManager(env.getRequiredProperty(AppEnvPropertyConstants.JmsConstants.IPREO_MQ_QUEUE_MGR));
mqConnectionFactory.setPort(env.getRequiredProperty(AppEnvPropertyConstants.JmsConstants.IPREO_MQ_PORT, Integer.class));
mqConnectionFactory.setChannel(env.getRequiredProperty(AppEnvPropertyConstants.JmsConstants.IPREO_MQ_CHANNEL));
//mqConnectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
//Setting connection mode as Client so it doesn't complain for native IBM MQ libraries
mqConnectionFactory.setIntProperty(CommonConstants.WMQ_CONNECTION_MODE, CommonConstants.WMQ_CM_CLIENT);
} catch (JMSException exception) {
exception.printStackTrace();
}
cachingConnectionFactory.setTargetConnectionFactory(mqConnectionFactory);
//Setting session caching size as 10, don't think we need more
cachingConnectionFactory.setSessionCacheSize(10);
cachingConnectionFactory.setReconnectOnException(true);
return cachingConnectionFactory;
}
public DefaultMessageListenerContainer ipreoDealActivityListenerContainer() {
DefaultMessageListenerContainer factory = new DefaultMessageListenerContainer();
factory.setConnectionFactory(ipreoMQCachingConnectionFactory());
factory.setDestinationName(env.getRequiredProperty(AppEnvPropertyConstants.JmsConstants.IPREO_DEAL_QUEUE_NAME));
factory.setMessageListener(ipreoDealActivityListener());
factory.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);
return factory;
}
@Bean
public MessageListener ipreoDealActivityListener() {
return new IpreoDealActivityListener();
}
感谢你的帮助,谢谢。
添加延迟响应,因为它可能对某人有用。
在我的案例中,当java客户端出现此异常时,我们注意到实际消息大小大于默认的4MB缓冲区大小。
Java API不提供用于更改缓冲区大小的挂钩。因此,缓冲区大小必须在MQ服务器级别进行更新。
首先,我们增加了队列属性中的消息大小——这不起作用。
然后,我们还增加了MQ通道级别的消息大小属性,这最终解决了问题。
总之,增加MQ服务器上队列&两个频道
在与队列管理器的客户端连接上,您可以限制服务器端和客户端的消息大小。当客户端限制小于消息大小时,我以前见过这种错误。
我不知道如何直接在JMS客户端中设置消息大小限制,但可以使用客户端通道定义表。它是一个文件,包含连接到队列管理器的详细信息,在队列管理器上创建,然后复制到客户端主机。您需要通过在连接工厂上发出setCCDTURL来引用该文件(使用CCDT时不需要设置主机、端口和通道,CCDT将指定这些)。
在队列管理器上创建CCDT时,需要在客户端通道上设置适当的消息大小限制。
服务器端限制是在服务器连接通道上设置的。
在JMS客户端中,接收缓冲区的代码处理是我们自动处理的;理论上,JMS应用程序永远不应该接收到特定的错误。
第一段代码是Java类API,这可能会导致错误。
这些信息到底有多大?您使用的JMS客户端代码的级别是什么?请确保它是最新版本。当然还有7.5或8版本中的一个。
这个答案也提供了更多的信息。