SAF(Store and forward)機能について

しばらく更新が滞っていましたが、RubyConf2006までにバージョンアップすべく、追加機能を実装中です。
次のバージョンでは以下の機能が加わります。

AP4Rでは、非同期処理のトリガーとなる捌き屋スレッドがDB(ないしファイル)に永続化されたメッセージを取り出してWebサーバに送信しています。このときのプロトコルに従来まではXML-RPCを使用していましたが、新たにSOAPとべたなHTTPを追加します。
XML-RPCSOAPもHTTP POSTメソッド経由なので微妙な表現ですが... (^^;


XML-RPCでは値渡しにStructが必要になりますし、SOAPではwsdlをサーバ側に定義する必要があります。このあたりが面倒なのでべたにHTTPで送る口を用意しました。詳しい話はまたのちほど...


  • SAF(Store and forward)による信頼性の向上

非同期メッセージングで重要な概念に、QoS (Quality of Service)があります。さまざまなMOM (Message-Oriented Middleware)でサポートされているもので、いくつかの種類とレベルがありますが、そのひとつにネットワーク障害やサーバクラッシュ時のメッセージ保障に関するレベルがあります。
BEAのWebLogicを例にあげると、以下のように定義されています。

  • Selecting a Quality-of-Service (QOS) Level

http://edocs.bea.com/wls/docs92/bridge/design.html#wp1174403

だいたいこんな感じの内容です。

  1. at-most-once: メッセージが重複して配信されることがないことを保証します(失われることはあり得ることに注意)。
  2. at-least-once: メッセージが失われることがないことを保証します。
  3. exactly-once: 最も高いQoSレベルで、at-least-onceかつat-most-onceで配信します。つまりメッセージは必ずただ1度配信されることを保証します。once-and-only-onceとも呼ばれます。

※高いQoSレベルを要求するということはそのための制御を必要とし、それはすなわちパフォーマンスに影響します。高いQoSはパフォーマンスと常にトレードオフの関係にあります。


今回の機能追加ではreliable-msgのクライアント側でSAFの仕組みを導入し、at-least-onceを実現しています。すなわち、メッセージが失われることがないことを保障します。
#at-most-onceの仕組みも実は準備してあるのですが、まともなアプリケーションであれば同一の処理が2度実行された場合のハンドリングはしてあるはずなので、無駄なオーバーヘッドを省くべく今回は敢えて入れていません。運用面への考慮も必要になってくるのでよく考えてみます。


そもそもどうしてメッセージが失われる場合があるのかについては「SAF」とかでぐぐればたくさんでてくると思います。 (^^;

はしょって説明すると、、、
アプリケーションの永続化先とMOMの永続化先が異なる場合、それぞれの永続化先へのcommitタイミングに差がでます。この差の間に障害が発生しするとメッセージが失われたり、不要なメッセージが発生することになります。2フェーズコミット(2PC)を利用することでこの差を埋めることはできますが、一般に2PCのコストは高く、障害時のリカバリも難しくなるのであまりお勧めできません。


そこで登場するのがSAFです。
アプリケーション側の永続化先にSAF用のテーブルを設け、ここにMOMに永続化予定のメッセージとその付随情報をいったん格納(store)します。そして、このタイミングでいったんアプリケーション側の永続化先をcommitします(格納に失敗したらもちろんrollbackします)。その後、MOMにメッセージを永続化してcommit、SAFテーブルのステータスを更新してcommit、という流れになります(forward)。


 1.アプリ用のDB内の各種テーブルの操作(登録/更新/削除)
 2.アプリ用のDB内のSAFテーブルへ登録
 3.アプリ用のDBのcommit
 4.MOM用のDB内のメッセージ格納用テーブルへ登録
 5.MOM用のDBのcommit
 6.アプリ用のDB内のSAFテーブルの更新
 7.アプリ用のDBのcommit


こうすることによって、前処理がエラーになった場合は後処理はけっして実行せず、逆に前処理が正常だった場合には確実に後処理のためのメッセージが残ることになります。commit時の微妙なタイミングで障害が発生しても安心です。しかも、SAFテーブルはアプリ用のDB内にあるので、2PCのようにコストが高くなることもありません。


Railsプラグインした際の利用方法については、次回のエントリで紹介したいと思います♪