4

同じマシンに 2 つの HornetQ (2.2.14) スタンドアロン サーバー (ライブ バックアップ サーバー) があります。次のシナリオを検討してください。

  1. ライブ サーバーがクラッシュしました。バックアップ サーバーは現在稼働中です。
  2. クライアント A (ライブ サーバーがクラッシュしたことを知らない) は、ライブ サーバーに接続する必要があります (ライブ サーバーの JNDI プロバイダーを使用して接続ファクトリを検索する必要があります)。
  3. クライアント A はライブ サーバーの JNDI プロバイダーを見つけることができないため、バックアップ サーバーに接続する必要があります (バックアップ サーバーの JNDI プロバイダーを使用して接続ファクトリを検索する必要があります)。

クライアント A のJNDI プロバイダー (URL の変更)を動的に変更するにはどうすればよいですか? JNDI フェイルオーバーの方法はありますか?

私は春に統合されたアプリケーションを持っており、それは私の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. メッセージを送る

このようなもの (それは私の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.");
        }

しかし、これには非常に時間がかかります (約 2 秒に 1 つのメッセージ)!!!

4

1 に答える 1

0

私がここで見つけたのは2つのことです

最初に 1 つのグローバル フラグを設定し、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ブロックの2番目のものは、特定の例外に対して宣言します。パフォーマンスにも影響します。

于 2012-11-20T13:40:35.333 に答える