フォールトトレラントなJMSサーバーとして機能するようにクラスター化されたJBoss5.1サーバーのペアがあります。
MySQLデータストアを使用するように構成し(mysql-persistence-service.xmlでクラスタリング設定を有効にして)、次のように定義して、destinations-service.xmlにトピックmbeanを作成しました。
<mbean code="org.jboss.jms.server.destination.TopicService" name="jboss.messaging.destination:service=Topic,name=ECM-PRM-Topic" xmbean-dd="xmdesc/Topic-xmbean.xml">
<depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
<depends>jboss.messaging:service=PostOffice</depends>
<attribute name="Clustered">true</attribute>
<attribute name="SecurityConfig">
<security>
<role name="ecm-role" write="true" />
<role name="prm-role" read="true" create="true" />
</security>
</attribute>
私のクライアント(J2SE!)は、以下を使用してこのJMSサーバーに接続しています。
// Step 1. Create an initial context to perform the JNDI lookup.
initialContext = new InitialContext(p);
// Step 3. Perform a lookup on the Connection Factory
ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ClusteredConnectionFactory");
// Step 2. Perfom a lookup on the queue
Destination target = (Destination)initialContext.lookup("/topic/ECM-PRM-Topic");
次の一連のイベントが発生した場合:
- Node1はアップ、Node2はダウンです。
- クライアントはJMSに接続し、トピック「ECM-PRM-Topic」で永続サブスクライバーを作成します。
- クライアントが切断され、永続サブスクリプションが残ります。
- 他のクライアントは、トピック「ECM-PRM-トピック」に関するメッセージを公開しています。
- Node1がダウンします。
- Node2が起動します。
- 他のクライアントは、トピック「ECM-PRM-トピック」に関するメッセージを再度公開します。
- クライアントは永続サブスクリプションに再度接続します。
- クライアントが切断します
- ノード1が起動します。
- クライアントは永続サブスクリプションに再度接続します。
手順4で公開されたメッセージはデータベースに保存され、クライアントが再接続するのを待っています(MySQLで確認できます)。(それで大丈夫です)
手順6で開始されたノードは、そのトピックに関する永続的なサブスクリプションを認識していません。(なぜ??)
手順7で公開されたメッセージはすぐに消えます。(既知の耐久性もクライアントも接続されていないため)
ステップ8でクライアントが接続すると、新しい耐久性が作成され、メッセージは配信されません(ただし、MySQLにはまだメッセージがあります)。
ステップ10で、クライアントは、ステップ7からのメッセージを除いて、耐久性からすべてのメッセージを受信します。魔女は完全に失われます。
メッセージが失われないことを100%保証したいと思います。すべてのメッセージは、クライアントによって消費されるまで、耐久性のあるMySQLデータベースに保存する必要があります。
何が悪いのか提案はありますか?
(クライアントがDurableSubscriberを作成する前に)XMLファイルでJBossに永続サブスクリプションを設定する方法はありますか?
私が使用する完全なクライアントコードはここにあります