我可以从 Spring 连接到 EMS 队列,并且使用此配置可以正常工作:
@Configuration
@EnableJms
public class TibcoJmsConfiguration {
public static final String SUN_AND_IBM_JSSE_SUPPORT = "j2se-default";
private final ParameterService parameterService;
private final ServerConfig serverConfig;
public TibcoJmsConfiguration(ParameterService parameterService, ServerConfig serverConfig) {
this.parameterService = parameterService;
this.serverConfig = serverConfig;
}
//based on TibcoJmsInitialContext.class
@Bean(name = "tibJmsConnectionFactory")
public ConnectionFactory connectionFactory() throws NamingException, JMSException {
// custom fault-tolerant system because url divided by comma not working:
// serverUrl = tcp://server0:7222,tcp://server1:7344
// workaround: use db value + restart jvm
String emsQueueUrl = parameterService.getEmsQueueUrl();
return getTibjmsConnectionFactory(emsQueueUrl);
}
@NotNull
private TibjmsConnectionFactory getTibjmsConnectionFactory(String emsQueueUrl) {
final TibjmsConnectionFactory connectionFactory = new TibjmsConnectionFactory(emsQueueUrl);
// https://docs.tibco.com/pub/ems/8.6.0/doc/html/GUID-CE5017DD-EF33-417A-AE0F-59DA05FA7BC7.html
connectionFactory.setConnAttemptCount(5);
connectionFactory.setConnAttemptDelay(1000);
connectionFactory.setConnAttemptTimeout(1000);
connectionFactory.setUserName(serverConfig.getConfigValue(CRM_USER));
connectionFactory.setUserPassword(serverConfig.getConfigValue(CRM_PWD));
connectionFactory.setSSLIdentity(serverConfig.getConfigValue(CRM_SSL_IDENTITY));
connectionFactory.setSSLPassword(serverConfig.getConfigValue(CRM_SSL_PASSWORD));
connectionFactory.setSSLDebugTrace(serverConfig.getConfigBoolean(CRM_DEBUG));
connectionFactory.setSSLTrace(serverConfig.getConfigBoolean(CRM_TRACE));
connectionFactory.setSSLTrustedCertificate(serverConfig.getConfigValue(CRM_SSL_TRUSTED));
connectionFactory.setSSLEnableVerifyHost(false);
connectionFactory.setSSLVendor(SUN_AND_IBM_JSSE_SUPPORT);
return connectionFactory;
}
@Bean
public BackOff getFixedBackOff(){
//block attempt connection
FixedBackOff backOff = new FixedBackOff();
backOff.setMaxAttempts(5);
backOff.setInterval(5000);
return backOff;
}
@Bean
public JmsListenerContainerFactory jmsListenerContainerFactory(@Qualifier("tibJmsConnectionFactory") ConnectionFactory connectionFactor) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactor);
factory.setBackOff(getFaultTolerantBackOff());
return factory;
}
public ConnectionFactory connectionFactory(String url) {
return getTibjmsConnectionFactory(url);
}
}
其中
emsQueueUrl
就像 ssl://ms-server-1:1234,ssl://ms-server-2:1234
。
一开始它甚至会检测到
ms-server-1
是否已按下并切换到 ms-server-2
。
我有一个带有
@JmsListener
的课程,它接收消息:
@Component
public class CrmEventReceiver {
private final CrmEventService crmEventService;
private final ServerConfig serverConfig;
private final ParameterService parameterService;
public CrmEventReceiver(CrmEventService crmEventService, ServerConfig serverConfig, ParameterService parameterService) {
this.crmEventService = crmEventService;
this.serverConfig = serverConfig;
this.parameterService = parameterService;
}
@JmsListener(destination = "AGPI.QL.MY_EVENT_INPUT")
public void receiveMessage(Object messageInput) {
try {
TextMessage message = (TextMessage) messageInput;
notNull(message, "[CRM_EVENT] TibcoJMSTextMessage - Could not receive message");
lEvent(message.getText());
} catch (Exception exception) {
LOGGER.error("[CRM_EVENT] TibcoJMSTextMessage - Could not convert message into TibjmsTextMessage", exception);
}
} else {
LOGGER.info("[CRM_EVENT] Message not read because the queue is not active");
}
}
}
我遇到的问题是,如果在运行时期间从一台 EMS 服务器切换/故障转移到第二台,那么我的侦听器将失败。我希望 JMS 立即重新连接到辅助服务器,但事实并非如此。它在关闭的服务器上一遍又一遍地循环。我发现停止重试循环的唯一方法是使用
FixedBackOff
。
您知道如何配置 Spring 和 Tibco JMS 在“灾难恢复”期间自动从一台服务器切换到另一台服务器吗?
我尝试了多种 EMS/队列配置,创建了自己的自定义
FixedBackOff
类来实时重新加载第二台服务器上的 JMS 侦听器,但我的尝试性解决方案都不起作用。
要了解应用程序使用的确切配置及其在与 EMS 服务器的连接丢失后的行为,您可以在 EMS 服务器级别启用客户端跟踪。 完成后,您将在应用程序的标准输出中收到调试消息。可以使用 tibemsadmin 使用以下命令对所有客户端应用程序完成此操作: 设置服务器 client_trace 启用 您可以通过添加客户端 ID 来指定给定客户端,如下所示: 设置服务器 client_trace 启用 clientid=XXXXX
根据您提供的元素,我可以建议尝试以下操作:
使用以下方法将重新连接参数添加到您的工厂(您的代码中缺少此参数)
connectionFactory.setReconnAttemptCount(10) connectionFactory.setReconnAttemptDelay(10000) connectionFactory.setReconnAttemptTimeout(1000)
(请注意,上面的操作会每 10 秒重试 10 次)
client_heartbeat_server = 20 server_timeout_client_connection = 90 server_heartbeat_client = 20 client_timeout_server_connection = 90
ft_reconnect_timeout=300
(一旦新的 EMS 服务器处于活动状态,上述客户端有 5 分钟的时间重新连接,一旦此延迟到期,客户端应用程序将必须打开新连接)