Tibco EMS JMS 容错功能不适用于 Spring Boot

问题描述 投票:0回答:1

我可以从 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 侦听器,但我的尝试性解决方案都不起作用。

spring spring-boot jms spring-jms tibco-ems
1个回答
0
投票

要了解应用程序使用的确切配置及其在与 EMS 服务器的连接丢失后的行为,您可以在 EMS 服务器级别启用客户端跟踪。 完成后,您将在应用程序的标准输出中收到调试消息。可以使用 tibemsadmin 使用以下命令对所有客户端应用程序完成此操作: 设置服务器 client_trace 启用 您可以通过添加客户端 ID 来指定给定客户端,如下所示: 设置服务器 client_trace 启用 clientid=XXXXX

根据您提供的元素,我可以建议尝试以下操作:

  1. 使用以下方法将重新连接参数添加到您的工厂(您的代码中缺少此参数)

    connectionFactory.setReconnAttemptCount​(10) connectionFactory.setReconnAttemptDelay​(10000)  connectionFactory.setReconnAttemptTimeout​(1000) 

(请注意,上面的操作会每 10 秒重试 10 次)

  1. 在 EMS 服务器配置中添加以下属性,以确保客户端应用程序可以检测到 EMS 服务器的连接丢失:

client_heartbeat_server = 20  server_timeout_client_connection = 90  server_heartbeat_client = 20  client_timeout_server_connection = 90

  1. 更新 EMS 服务器配置中的以下属性,以便为客户端应用程序重新连接提供时间
    ft_reconnect_timeout=300

(一旦新的 EMS 服务器处于活动状态,上述客户端有 5 分钟的时间重新连接,一旦此延迟到期,客户端应用程序将必须打开新连接)

© www.soinside.com 2019 - 2024. All rights reserved.