SOAでのトランザクション処理に関しては、ここ数年、継続して議論されてきた。BTP、WS-BusinessActivity、WS-AtomicTransactionやWS-Coordinationなどのいくつかの標準がこの問題を解決するために提案されてきたにも関わらず、広く受け入れられた解決策は未だに存在しない。Arnon Rotem-Gal-Oz氏は、新しい投稿の中で、彼の間もなく出版される新しい本(Practical SOA - Reservations pattern)からの引用を公開した。
Arnon氏はSOAのトランザクションに関する問題を次のように述べている。
SOAであろうがなかろうが、分散環境においては、アトミックな短期間のトランザクションを使うのは良い考えではありません。私たちがSagaパターンを使う主な理由は、サービスをまたいだトランザクションを利用しないようにするためです。Sagaパターンの明確な欠点の一つは、ロールバックを実行できないというものです。しかし、インタラクション、特にロングランニングのインタラクションは失敗することもあれば、キャンセルされることもあるので、Sagaパターンは、補償という考え方を提供しています。補償は次のような優れたものです。ロールバックを行うことができないので、代わりにインタラクションの操作を逆向きにした取り消し操作により、擬似的なロールバック処理を行うのです。残念なことに補償にはいくつかの問題があります。これらの問題は、ACIDトランザクションとは異なり、Sagaの各アクティビティで行われた変更に独立性がないことに起因します。独立性が欠けていると、あるSagaのアクティビティによって変更されたデータが、他のサービスによって操作される可能性があります。こうなってしまったら、補償処理を行うことは不可能なのです。
Arnon氏は、補償とSagaパターンの他の制限事項に関しても言及している。外部のコーディネータが必要となり、それによってサービスと外部のコーディネータとの間に望まざる結合が生じてしまうというものだ。
Arnon氏は投稿において、この問題を解消するためのパターンを提案している。
私たちはいかにして、疎結合の環境で、サービスに対して自立的かつ一貫したメンテナンスを行いつつ、効率的に一定の保証を提供することができるだろうか。
その回答であるReservationパターンでは、予約処理を扱う内部のサービス・コンポーネントの導入が必要となる。このコンポーネントの責務は次のようなものだ。
- 予約 - 「予約」と見なすメッセージがきた際に、予約を執り行う。例えば、注文を受け取った際には、永続化ストレージ(例えばデータベース)を更新するとともに注文確認が到着するまでのタイマもしくは有効期限を設定する。あるいは注文が最終決定していないことを示す目印を設定する。
- 検証 - プロセスが終了するまで予約が有効であることを保証する。先にあげたシナリオでは、注文に割り当てられた商品は、他の誰かに与えられないよう保証する。
- 期限切れ - 条件が変わったときに予約を無効化する。例えば、VIP顧客が私の予約した商品を欲した場合、システムはそれを彼に割り当てることができる。さらに私の予約を無効化して、私が請求したときに、システムは商品が既にないことを知っていなければならない。無効化は、時間でも設定できる。明日の正午まで本を予約でとっておくというように。
このパターンは2パス・プロトコルを実装する手順で、リソースの割当プロセスを管理することを可能にする(2相コミットと幾分似ている)。最初のパスでは、プロセスを開始したものが、各参加者に予約を行うように依頼する。もし全ての関連するサービスから(タイムアウト時間以内に)OKと受け取ると、2つめのパスを始めて、すべての参加者に予約確認を行う。
多くのSOAパターンと異なり、Reservationパターンは、テクノロジのパターンというよりは、ビジネスのパターンだ。これは、実装するための1対1の技術上のマッピングが存在しないことを意味する。Arnon氏は、EJB3.0をベースとしたパターンの実装に関しても述べている。
トランザクション処理が今日のソフトウェア技術の土台となっており、分散コンピューティングを信頼がおける管理可能なものにし、輸送や金融、保険、通信、製造などの大企業で利用され、ファンドの移動や、給与支払、電子コミュニケーション、在庫コントロールやその他の処理がトランザクション処理に依存していることを考えると、何らかの形のトランザクションをSOAで実装することはこの上なく重要なことである。Arnon氏の投稿で定義されたReservationパターンは、SOAアーキテクトの道具箱のなかの重要な道具の一つである。
しかし次のような疑問がある。サービスはお互いに呼びあうべきなのだろうか、それともサービス呼び出しを制御するプロセスが存在するべきなのだろうか。後者の場合、そのようなプロセスは事実上コーディネータとなり、もしサービスのインターフェースがアクションと補償の双方をサポートしているのであれば、Sagaパターンがより単純なソリューションとなるだろう。