在 JVM 集群中使用 JMS 的 IBM MQ 侦听器
IBM MQ listener using JMS in a JVM cluster
我已经为 IBM MQ 设置了一个 JMS 侦听器。当侦听器在单个 JVM 上为 运行 时,如在本地计算机上为 tomcat,它运行良好。但是当我将它部署到有 2 个虚拟机的云时,它在其中一个虚拟机上 运行 正常并连接到 MQ,但它在另一个虚拟机上显示如下。
IBM MQ 对使用来自多个客户端的 ID、密码连接到队列管理器是否有任何限制?
RROR> com.ssc.ach.mq.JMSMQReceiver[main]: errorMQJMS2013: invalid security authentication supplied for MQQueueManager
javax.jms.JMSSecurityException: MQJMS2013: invalid security authentication supplied for MQQueueManager
at com.ibm.mq.jms.MQConnection.createQM(MQConnection.java:2050)
at com.ibm.mq.jms.MQConnection.createQMNonXA(MQConnection.java:1532)
at com.ibm.mq.jms.MQQueueConnection.<init>(MQQueueConnection.java:150)
at com.ibm.mq.jms.MQQueueConnectionFactory.createQueueConnection(MQQueueConnectionFactory.java:185)
at com.ibm.mq.jms.MQQueueConnectionFactory.createConnection(MQQueueConnectionFactory.java:1066)
at
我正在使用 Servlet init 方法在 VM 启动时启动侦听器
public void init(ServletConfig config) throws ServletException {
logger.info("App Init");
try {
boolean isListnerOn = Boolean.parseBoolean(System.getProperty("listner", "false"));
logger.info(" startReceiver , listner flag is "+isListnerOn);
if(isListnerOn){
if (mqReceive == null) {
MyMessageListener jmsListner = new MyMessageListener();
mqReceive = new JMSMQReceiver(jmsListner);
}
if (mqReceive != null) {
try{
mqReceive.start();
} catch (Exception e) {
logger.error("Error starting the listner ", e);
}
}
}else{
logger.info(" listner not started as flag is "+isListnerOn);
}
} catch (Exception e) {
logger.error(e, e);
}
}
private MQQueueConnectionFactory mqQueueConnectionFactory;
public MQReceiver(MyMessageListener listner) {
userName=System.getProperty( "mqId","");
pwd=System.getProperty("mqId","");
host = System.getProperty(PREFIX + ".host");
port = Integer.parseInt(System.getProperty(PREFIX + ".port"));
qManager = System.getProperty(PREFIX + ".qManager");
channel = System.getProperty(PREFIX + ".channel");
queueName = System.getProperty(PREFIX + ".achqueueName");
logger.info("HOST:" + host + "\tPORT:" + port + "\tqManager:"+ qManager + "\tchannel:" + channel + "\tqueueName:"+ queueName);
try {
mqQueueConnectionFactory = new MQQueueConnectionFactory();
mqQueueConnectionFactory.setHostName(host);
mqQueueConnectionFactory.setChannel(channel);//communications link
mqQueueConnectionFactory.setPort(port);
mqQueueConnectionFactory.setQueueManager(qManager);//service provider
mqQueueConnectionFactory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
queueConnection = mqQueueConnectionFactory.createConnection(trustUserName, trustID);
session = queueConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
queue = session.createQueue(queueName);
((MQDestination) queue).setTargetClient(WMQConstants.WMQ_CLIENT_NONJMS_MQ);
MessageConsumer consumer = session.createConsumer(queue);
consumer.setMessageListener(listner);
logger.info(" Connect MQ successfully.");
} catch (JMSException e) {
logger.error("error" + e.getMessage(), e);
}
}
public void start() {
logger.info("Starting MQListener... ");
//mqListener.start();
try {
queueConnection.start();
logger.info("MQListener start successfully");
} catch (JMSException e) {
logger.error("error" + e.getMessage(), e);
}
}
com.ssc.ach.mq.JMSMQReceiver[main]: errorMQJMS2013: invalid security authentication supplied for MQQueueManager
javax.jms.JMSSecurityException: MQJMS2013: invalid security authentication supplied for MQQueueManager
是因为:
queueConnection = mqQueueConnectionFactory.createConnection(trustUserName, trustID);
如果您不提供可由队列管理器验证的有效用户 ID 和密码,那么您的连接将被拒绝。我不知道您要传递给该方法的是什么,但它应该是远程系统的有效用户 ID 和密码。
此外,我希望人们停止使用术语 'MQ Listener',因为您不是在创建 'MQ Listener',而是在创建接收消息的消费者。
MQ 侦听器是 MQ 的一个组件,用于接受和处理传入连接。参见 here。
IBM MQ 类 for JMS 客户端错误 JMSWMQ2013
可能由很多问题引起。
IBM 支持技术说明“WMQ 7.1 / 7.5 / 8.0 / 9.0 queue manager RC 2035 MQRC_NOT_AUTHORIZED or AMQ4036 or JMSWMQ2013 when using client connection as an MQ Administrator”有一篇关于诊断和解决此类问题的好文章。
如果您需要更具体的帮助,首先请通过编辑并添加到您的问题中来提供以下详细信息。
- 客户端应用程序使用的 JMS 的 IBM MQ 类 版本。
- IBM MQ 队列管理器上安装的 IBM MQ 版本
- 队列管理器 AMQERR01.LOG 中的错误与您在 IBM MQ 类 中针对第二个 VM 上的 JMS 客户端应用程序收到的错误同时发生。
奇怪的是,它在第一个 VM 上运行,但在第二个 VM 上失败。如果两个 VM 的 trustUserName 和 trustID 相同,IBM MQ 应该同样接受它们。
如果您使用的是 IBM MQ v8 或更高版本的本机连接身份验证,则 OS 或 PAM 可能会拒绝第二个连接。我只看到 pam_tally 的限制为 5 并且同时命中的连接超过 5 个。可能存在某种登录限制,每个用户只能登录一次。
根据您的评论,您似乎缺少 CHLAUTH ADDRESSMAP 规则,允许使用第一个 VM 的 IP 而不允许使用第二个 VM 的 IP。根据队列管理器的配置方式以及 CHLAUTH 规则阻止连接的方式,队列管理器可能 return MQRC 2035 到客户端。在用于 JMS 客户端的 IBM MQ 类 上,它被 return 编辑为 MQJMS2013。例如,如果您的队列管理器正在使用 ADOPTCTX(NO)
并且具有将 ADDRESS(*)
映射到不存在的 MCAUSER
的 CHLAUTH 规则(例如:*NOACCESS
)和其他CHLAUTH 规则将连接从特定 IP 映射到具有访问权限的用户。
更安全的设置是使用 ADOPTCTX(YES)
,它会告诉 MQ 将 MCAUSER
设置为由 CONNAUTH 验证的 ID。您还可以使用 ADDRESS(*) USERSRC(NOACCESS)
默认阻止的地址映射规则,然后使用特定 IP 和 USERSRC(CHANNEL
的其他规则来允许那些您想要列入白名单的 IP。
我已经为 IBM MQ 设置了一个 JMS 侦听器。当侦听器在单个 JVM 上为 运行 时,如在本地计算机上为 tomcat,它运行良好。但是当我将它部署到有 2 个虚拟机的云时,它在其中一个虚拟机上 运行 正常并连接到 MQ,但它在另一个虚拟机上显示如下。
IBM MQ 对使用来自多个客户端的 ID、密码连接到队列管理器是否有任何限制?
RROR> com.ssc.ach.mq.JMSMQReceiver[main]: errorMQJMS2013: invalid security authentication supplied for MQQueueManager
javax.jms.JMSSecurityException: MQJMS2013: invalid security authentication supplied for MQQueueManager
at com.ibm.mq.jms.MQConnection.createQM(MQConnection.java:2050)
at com.ibm.mq.jms.MQConnection.createQMNonXA(MQConnection.java:1532)
at com.ibm.mq.jms.MQQueueConnection.<init>(MQQueueConnection.java:150)
at com.ibm.mq.jms.MQQueueConnectionFactory.createQueueConnection(MQQueueConnectionFactory.java:185)
at com.ibm.mq.jms.MQQueueConnectionFactory.createConnection(MQQueueConnectionFactory.java:1066)
at
我正在使用 Servlet init 方法在 VM 启动时启动侦听器
public void init(ServletConfig config) throws ServletException {
logger.info("App Init");
try {
boolean isListnerOn = Boolean.parseBoolean(System.getProperty("listner", "false"));
logger.info(" startReceiver , listner flag is "+isListnerOn);
if(isListnerOn){
if (mqReceive == null) {
MyMessageListener jmsListner = new MyMessageListener();
mqReceive = new JMSMQReceiver(jmsListner);
}
if (mqReceive != null) {
try{
mqReceive.start();
} catch (Exception e) {
logger.error("Error starting the listner ", e);
}
}
}else{
logger.info(" listner not started as flag is "+isListnerOn);
}
} catch (Exception e) {
logger.error(e, e);
}
}
private MQQueueConnectionFactory mqQueueConnectionFactory;
public MQReceiver(MyMessageListener listner) {
userName=System.getProperty( "mqId","");
pwd=System.getProperty("mqId","");
host = System.getProperty(PREFIX + ".host");
port = Integer.parseInt(System.getProperty(PREFIX + ".port"));
qManager = System.getProperty(PREFIX + ".qManager");
channel = System.getProperty(PREFIX + ".channel");
queueName = System.getProperty(PREFIX + ".achqueueName");
logger.info("HOST:" + host + "\tPORT:" + port + "\tqManager:"+ qManager + "\tchannel:" + channel + "\tqueueName:"+ queueName);
try {
mqQueueConnectionFactory = new MQQueueConnectionFactory();
mqQueueConnectionFactory.setHostName(host);
mqQueueConnectionFactory.setChannel(channel);//communications link
mqQueueConnectionFactory.setPort(port);
mqQueueConnectionFactory.setQueueManager(qManager);//service provider
mqQueueConnectionFactory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
queueConnection = mqQueueConnectionFactory.createConnection(trustUserName, trustID);
session = queueConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
queue = session.createQueue(queueName);
((MQDestination) queue).setTargetClient(WMQConstants.WMQ_CLIENT_NONJMS_MQ);
MessageConsumer consumer = session.createConsumer(queue);
consumer.setMessageListener(listner);
logger.info(" Connect MQ successfully.");
} catch (JMSException e) {
logger.error("error" + e.getMessage(), e);
}
}
public void start() {
logger.info("Starting MQListener... ");
//mqListener.start();
try {
queueConnection.start();
logger.info("MQListener start successfully");
} catch (JMSException e) {
logger.error("error" + e.getMessage(), e);
}
}
com.ssc.ach.mq.JMSMQReceiver[main]: errorMQJMS2013: invalid security authentication supplied for MQQueueManager
javax.jms.JMSSecurityException: MQJMS2013: invalid security authentication supplied for MQQueueManager
是因为:
queueConnection = mqQueueConnectionFactory.createConnection(trustUserName, trustID);
如果您不提供可由队列管理器验证的有效用户 ID 和密码,那么您的连接将被拒绝。我不知道您要传递给该方法的是什么,但它应该是远程系统的有效用户 ID 和密码。
此外,我希望人们停止使用术语 'MQ Listener',因为您不是在创建 'MQ Listener',而是在创建接收消息的消费者。
MQ 侦听器是 MQ 的一个组件,用于接受和处理传入连接。参见 here。
IBM MQ 类 for JMS 客户端错误 JMSWMQ2013
可能由很多问题引起。
IBM 支持技术说明“WMQ 7.1 / 7.5 / 8.0 / 9.0 queue manager RC 2035 MQRC_NOT_AUTHORIZED or AMQ4036 or JMSWMQ2013 when using client connection as an MQ Administrator”有一篇关于诊断和解决此类问题的好文章。
如果您需要更具体的帮助,首先请通过编辑并添加到您的问题中来提供以下详细信息。
- 客户端应用程序使用的 JMS 的 IBM MQ 类 版本。
- IBM MQ 队列管理器上安装的 IBM MQ 版本
- 队列管理器 AMQERR01.LOG 中的错误与您在 IBM MQ 类 中针对第二个 VM 上的 JMS 客户端应用程序收到的错误同时发生。
奇怪的是,它在第一个 VM 上运行,但在第二个 VM 上失败。如果两个 VM 的 trustUserName 和 trustID 相同,IBM MQ 应该同样接受它们。
如果您使用的是 IBM MQ v8 或更高版本的本机连接身份验证,则 OS 或 PAM 可能会拒绝第二个连接。我只看到 pam_tally 的限制为 5 并且同时命中的连接超过 5 个。可能存在某种登录限制,每个用户只能登录一次。
根据您的评论,您似乎缺少 CHLAUTH ADDRESSMAP 规则,允许使用第一个 VM 的 IP 而不允许使用第二个 VM 的 IP。根据队列管理器的配置方式以及 CHLAUTH 规则阻止连接的方式,队列管理器可能 return MQRC 2035 到客户端。在用于 JMS 客户端的 IBM MQ 类 上,它被 return 编辑为 MQJMS2013。例如,如果您的队列管理器正在使用 ADOPTCTX(NO)
并且具有将 ADDRESS(*)
映射到不存在的 MCAUSER
的 CHLAUTH 规则(例如:*NOACCESS
)和其他CHLAUTH 规则将连接从特定 IP 映射到具有访问权限的用户。
更安全的设置是使用 ADOPTCTX(YES)
,它会告诉 MQ 将 MCAUSER
设置为由 CONNAUTH 验证的 ID。您还可以使用 ADDRESS(*) USERSRC(NOACCESS)
默认阻止的地址映射规则,然后使用特定 IP 和 USERSRC(CHANNEL
的其他规则来允许那些您想要列入白名单的 IP。