动态更改JNDI提供程序

时间:2012-11-20 08:30:25

标签: java spring jms jndi hornetq

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

  1. 直播服务器已崩溃,备份服务器现已启用。
  2. 客户端A (不知道Live服务器崩溃)想要连接到Live服务器(它应该使用 Live服务器JNDI提供程序<查找其连接工厂 / em>的)。
  3. 客户端A找不到Live服务器JNDI提供程序,因此它应该连接到备份服务器(它应该使用备份服务器JNDI提供程序查找其连接工厂)。
  4. 如何更改客户端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>
    

    更新 我可以通过这种方式处理在我的应用程序中从当前的live serrver查找连接工厂: 对于每条消息,

    1. 检查可用的JNDI提供程序(来自当前的实时服务器)
    2. 查找连接工厂
    3. 发送消息
    4. 这样的东西(来自我的 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.");
              }
      

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

1 个答案:

答案 0 :(得分:0)

我在这里找到的是两件事

首先设置一个全局标志并放入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块中的第二件事而不是异常将其声明为特定异常。它也会影响表现。