Spring JMS+IBM MQ:如何设置消息缓冲区大小或等待超时



我无法处理来自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版本中的一个。

这个答案也提供了更多的信息。

最新更新