java - 动态更改 JNDI 提供程序

标签 java spring jms jndi hornetq

我在同一台机器上有两个 HornetQ (2.2.14) 独立服务器(实时备份服务器);考虑这种情况:

  1. 实时服务器 崩溃,备份服务器 现已上线。
  2. 客户端 A(不知道 Live 服务器崩溃了)想要连接到 Live 服务器(它应该使用 Live 服务器 JNDI 提供程序<来查找其连接工厂/em>).
  3. 客户端 A 找不到实时服务器 JNDI 提供程序,因此它应该连接到备份服务器(它应该使用备份服务器 JNDI 提供程序查找其连接工厂)。

我如何为客户端 A 动态更改 JNDI 提供程序(更改 URL)? JNDI故障转移有什么办法吗?

我有一个 spring 集成应用程序,它是我的 applicationContext.xml:

<!-- Default JndiTemplate -->
        <bean id="defaultJndiTemplate" class="org.springframework.jndi.JndiTemplate">
            <property name="environment">
                <props>
                    <prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
                    <prop key="java.naming.factory.url.pkgs">org.jboss.naming:org.jnp.interfaces</prop>
                    <prop key="java.naming.provider.url">jnp://localhost:1099</prop>
                </props>
            </property>
        </bean>

 <!-- Backup JndiTemplate -->
        <bean id="backupJndiTemplate" class="org.springframework.jndi.JndiTemplate">
            <property name="environment">
                <props>
                    <prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
                    <prop key="java.naming.factory.url.pkgs">org.jboss.naming:org.jnp.interfaces</prop>
                    <prop key="java.naming.provider.url">jnp://localhost:2099</prop>
                </props>
            </property>
        </bean>

    <!-- Destinations -->
    <bean id="defaultDestination" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiTemplate" ref="defaultJndiTemplate" />
        <property name="jndiName" value="/queue/exampleQueue" />
    </bean>

    <!-- ConnectionFactories -->
    <bean id="defaultConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiTemplate" ref="defaultJndiTemplate" />
        <property name="jndiName" value="/ConnectionFactory" />
    </bean>

    <!-- JMS Template -->
    <bean name="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="defaultConnectionFactory" />
        <property name="sessionTransacted" value="true" />
    </bean>

    <!-- Message Producer -->
    <bean name="messageSender" class="messaging.producer.MessageSender">
        <property name="jmsTemplate" ref="jmsTemplate" />
        <property name="destination" ref="defaultDestination" />
    </bean>

更新: 我可以通过以下方式在我的应用程序中从当前实时服务器中查找连接工厂: 对于每条消息,

  1. 检查可用的 JNDI 提供程序(来自当前实时服务器)
  2. 查找连接工厂
  3. 发送消息

类似这样的东西(它来 self 的 MessageSender 类):

    //init initialContexts for live and backup servers
    public init() throws NamingException, CommunicationException
        {
            Hashtable<String, String> environment = new Hashtable<String, String>();
            environment.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
            environment.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
            environment.put(Context.PROVIDER_URL, "jnp://localhost:1099");
            initialContext_live = new InitialContext(environment);

            environment = new Hashtable<String, String>();
            environment.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
            environment.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
            environment.put(Context.PROVIDER_URL, "jnp://localhost:2099");
            initialContext_backup = new InitialContext(environment);

            jmsTemplate = new JmsTemplate();

        }
        //Sending message to toQueue
        public void send(final AbstractMessage message, String toQueue) throws NamingException 
        {
            Destination destination;
            try
            {
                connectionFactory = (ConnectionFactory)initialContext_live.lookup("/ConnectionFactory");
                jmsTemplate.setConnectionFactory(connectionFactory);
                destination = (Destination) initialContext_live.lookup(toQueue);
                System.out.print("[to-live]-");
            }
            catch(Exception e) //live server is down
            {
                connectionFactory = (ConnectionFactory)initialContext_backup.lookup("/ConnectionFactory");
                jmsTemplate.setConnectionFactory(connectionFactory);
                destination = (Destination) initialContext_backup.lookup(toQueue);
                System.out.print("[to-backup]-");
            }
            jmsTemplate.send(destination, new MessageCreator() 
            {
                @Override
                public Message createMessage(Session session) throws JMSException 
                {
                    ObjectMessage objMessage = session.createObjectMessage(message);
                    return objMessage;
                }
            });
            System.out.println("[MessageSender] Message sent.");
        }

但这非常耗时(大约两秒内一条消息)!!!

最佳答案

我在这里发现了两件事

首先你设置一个全局标志并放置if else条件

flag=true;
if(flag){
 try
        {
            connectionFactory =      (ConnectionFactory)initialContext_live.lookup("/ConnectionFactory");
            jmsTemplate.setConnectionFactory(connectionFactory);
            destination = (Destination) initialContext_live.lookup(toQueue);
            System.out.print("[to-live]-");
        }
}else{
connectionFactory = (ConnectionFactory)initialContext_backup.lookup("/ConnectionFactory");
            jmsTemplate.setConnectionFactory(connectionFactory);
            destination = (Destination) initialContext_backup.lookup(toQueue);
            System.out.print("[to-backup]-");
}
        catch(Exception e) //live server is down
        {
flag=false;
            connectionFactory = (ConnectionFactory)initialContext_backup.lookup("/ConnectionFactory");
            jmsTemplate.setConnectionFactory(connectionFactory);
            destination = (Destination) initialContext_backup.lookup(toQueue);
            System.out.print("[to-backup]-");
        } 

所以这里它不会检查实时服务器的代码,如果在它之间以某种方式丢失连接,它将直接连接到备份服务器

如果您的实时服务器已启动,您可以将标志设置为 true。

catch block 中的第二件事而不是异常声明它用于特定异常。它还会影响性能。

关于java - 动态更改 JNDI 提供程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13469208/

相关文章:

java - Oracle JRE 和 Dalvik JVM 上的不同结果

java - rpi 上的 OpenCV - System.loadLibrary 中的段错误

java - Maven 将实际 jar 生成为 .jar.original 而不是 .jar 文件

java - Spring 启动 : How to add interceptors to static resources?

java - 安慰消费者附加 MessageListener 警告

java - 将数据插入数据库时​​遇到问题

java - 如何将多个 bean 中定义的属性合并到单个(属性)bean 中?

java - Hibernate 子查询.exists

oracle - 为什么 OracleAQ 将死订户留在队列中?

java - 旧的垃圾收集已满且无法清理,可能是因为索引