同じマシンに 2 つの HornetQ (2.2.14) スタンドアロン サーバー (ライブ バックアップ サーバー) があります。次のシナリオを検討してください。
- ライブ サーバーがクラッシュしました。バックアップ サーバーは現在稼働中です。
- クライアント A (ライブ サーバーがクラッシュしたことを知らない) は、ライブ サーバーに接続する必要があります (ライブ サーバーの JNDI プロバイダーを使用して接続ファクトリを検索する必要があります)。
- クライアント 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>
更新: 次の方法で、アプリケーションの現在のライブ サーバーから接続ファクトリを検索できます。メッセージごとに、
- 利用可能な JNDI プロバイダーを確認する (現在のライブ サーバーから)
- 接続ファクトリーを調べる
- メッセージを送る
このようなもの (それは私の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 つのメッセージ)!!!