BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ アーティクル SOAの未来はRESTか

SOAの未来はRESTか

ブックマーク

原文(投稿日:2011/08/11)へのリンク

SOAの未来はRESTだという発言はどこへ行っても聞かされるようです。RESTとSOAPやWS*を比較した記事はたくさんあります[1]が、このような比較は単純すぎると思います。その中で、遅れて出てきた2つの手法があります。真のRESTとサービスのための技術方式としてのREST(いわゆるRESTウェブサービス[2])です。この記事ではどちらの方法がSOAの実装の改善に役立つのか詳しく調べようと思います。

SOAのための真のREST

真のRESTとはリソース指向アーキテクチャの実装のことであり、純粋な技術的な方針のことではありません。なので、RESTについて議論する場合の正しい質問は、この基礎にあるROAがSOAの実装と相性がいいかどうかなのです。

この問題を正確に評価するには、まずSOAというアーキテクチャスタイル[2]が企業のビジネスアーキテクチャの機能的な分解に基づいて、ビジネスサービスとビジネスプロセスというふたつの高度な抽象を導入する、ということを思い出す必要があります。ここで言うビジネスサービスとは既存のITの能力(企業のビジネスの機能と連携した)を表します。ビジネスプロセスはビジネスサービスを編成し、ビジネス全体の機能を定義します。

一方、RESTはリソース指向アーキテクチャ(ROA)として表された設計のガイドラインです。ROAを基礎付けるのはリソースという概念です。各リソースは直接アクセスできる分散化されたコンポーネントで、標準的、一般的な方法で扱うことができます。ROAの基礎はリソースを元にした分解[3]なのです。

RESTのSOAの実装への適用具合を評価するには、“サービスとリソースの関係はどのようなものか”という問いに答える必要があります。

サービス vs.リソース

サービスとはなにか

最も単純な場合、サービスは必要なものをすべて含んだ、独立して開発、配置、管理、メンテナンスができるソフトウエアの実装であり、企業の特定のビジネスと関係のある機能をに提供し、設計によって"統合可能"である、と言えます。ある“サービス”は動詞で定義できます(例えば、“顧客の信用度を検証する”、というふうに実現する機能を表現します)。

サービスはプログラミングの構成概念ではありません。APIのセットでもありません。むしろ、企業の問題解決のために実装される、設計物(部品の設計、実装、メンテナンス)と配置物です。サービスの機能性はサービスのインターフェイス(そのサービス特有の)によって定義されます。このインターフェイスは複数の実装方法で実現できます。サービスのインターフェイスを定義するにはふたつの基本的な方法があります。RPCスタイルとメッセージングスタイルです。RPCスタイルの実装はサービスの起動そのものがサービスの意味を表し、サービスはインターフェイスのパラメータによって定義されます。メッセージングスタイルの場合は、サービスのインターフェイスは事実上固定で、XML文書の入力と出力(GoFのコマンドパターンにとても似ていますが)によって“実行“されます。この場合サービスの意味は入出力されたメッセージの意味によって決まります[4]

歴史的には、サービスはメソッドの集合として定義されてきました。しかし、[2]が指摘するように、これらのメソッドは独立していて[5]、このようなメソッドの集合は名前空間として働き、サービスの管理を単純にしてくれます。

リソースとは何か

最も単純な場合、リソースは直接アクセスできる、独立して開発、配置、管理、メンテナンスができるソフトウエアであり、特定のデータをサポートします。リソースは名詞で定義されます。例えば、“医者’の予約”はリソースが提供するデータによって表現されます。リソースは他のリソースと関連し、参照(リンク)を提供します。実のところ、リソースはオブジェクト[6]に似ていますが、事前に定義された(CRUDな)インターフェイスを持っています。

RESTが持つ意味はHTTPの操作によって規定されます。下記を参照ください[5]。

  • createResource - 新しいリソース(と対応する一意な識別子)を作成する - PUT
  • getResourceRepresentation - リソースの表現を取得する - GET
  • deleteResource - リソースを削除する(関連するリソースもいっしょに削除できる) - DELETE (対象のリソースだけ)、POST (参照しているリソースも一緒に削除する場合)
  • modifyResource - リソースを変更する – POST
  • getMetaInformation - リソースのメタ情報を取得する - HEAD

リソースを定義するのはそのリソースのURLとそのリソースがサポートする各操作での入出力の仕様です[7]。メソッドが完全に独立していて、独立したエンドポイントとして配置できるサービスとは違い、リソースを操作するメソッドの意味の表現はオブジェクト指向の意味の表現方法に従います。つまり、すべて(createResourceを除いて)が潜在的にリソース上(同じURL)に存在しなければならないということです。

リソースとサービスの基本的な違い

上述したサービスとリソースの定義を元に考えると、両者が大きく違うのは直感的に分かると思います。まずこの違いについて詳しく掘り下げ、この違いが最終的な成果物であるアーキテクチャにどのような影響を与えるのか考えてみましょう。

[6]に書かれているように、

“RESTはサービス指向ではありません。サービス指向とは何の関係もないのです。”

さらに[7]はこの2つの違いを次のように説明します。

“WS-*がインターネットにおけるRPCなら、RESTはインターネットにおけるDBMSです。… 従来のSOAを使った統合は異なるソフトウエアがメソッドやプロシージャを使って相互に通信しているように見せました。RESTを使うと各ソフトウエアがテーブルの集合として振る舞い、各ソフトウエアはSELECT、INSERT、UPDATE、DELETE(または、GET、PUT、POST、DELETE)を使って互いにやり取りします。ビジネスロジックはどこにあるのでしょう。ストアドプロシージャの中でしょうか。いいえ、トリガのなかです。”

他の類推も使えます。J2EEで考えれば、サービスは状態を持たないセッションBeansでリソースはエンティティBeansです。

サービス、つまりセッションBeansはコントローラとして働き、必要な操作を潜在するリソースとは関係なく実行します。例えば、口座の引き落としサービスに必要なのは、口座のIDと口座の残高、そして引き落とし額です。単一のサービスでどの口座からも引き落としできます。

リソース、つまりエンティティBeansはあるデータ型のインスタンスのデータアクセスの仕組みとして働きます。例えば、引き落としをする場合、対象の口座を表すリソースを見つけ、必要な額を引き落とすために更新を行います。ここで注意したいのは、必要なメソッドは何でも実装できるエンティティbeanとは違って、リソースはリソース変更メソッドしか持ちません。つまり、引き落としのような実際のビジネス上の処理はリソースの変更要求のひとつとして解釈する必要があります。

つまりどういうことか

上述のことを考慮するとRESTを使ってSOAを構築するのは不可能です。システムを構築するのは可能ですが、それはSOAにはなりません。RESTもSOAもビジネスの一連のプロセスを分解します。しかし、分解の仕方が全く異なるので、成果物は全く違うコンポーネントとコネクタを使った全く違うアーキテクチャスタイル[8]になります。

ふたつともビジネス駆動でビジネスを分解することで、ビジネスとITの緊密な連携を実現しようとしますが、結果のアーキテクチャスタイルは同じにはなりません。

また、真のRESTを使ったシステムを完成させることは可能なのか、という疑問もあります。上述したことと合わせて考えれば、それはデータベースとエンティティだけでシステムを完成させることは可能なのか、という問いでもあります。可能かもしれませんが、ストアドプロシージャ(メソッドの意味を上書きして)やトリガ(データの変更を起点とした後処理のため)という形式で処理コードが必要になるはずです。真のRESTの実装でも同じことが言えます。データ更新以上のことをするにはmodifyResourceメソッドの意味を変えなければなりません(コマンドパターンを使って)。

つまり、RESTベースの実装が真のRESTであることはほとんどありません。RESTウェブサービスの要素を含んでいるのが普通です。ではRESTウェブサービスとはなんでしょうか。

RESTウェブサービス

RESTウェブサービスとは、RESTをSOAを構築するための通信技術として使う方法です。この場合、サービスはSOAの様式で定義され、RESTベースのウェブサービス[9]はトランスポートとして働きます。

このようなやり方が普通、RESTと言われますが、真のRESTとは無関係です。むしろPOX(単純なXML over HTTP)に似ています。違いと言えば、RESTはXML以外にもJavaScript Object Notation (JSON)、ATOM、バイナリラージオブジェクトなど複数のデータマーシャリングタイプをサポートします。また、POXは普通GETとPUTしか使いませんが、RESTの場合はそれ以外のHTTPメソッドも利用します。

JSONはとても人気があります。ウェブの技術が進歩し、Ajaxが広く普及したからです。現在のブラウザの大多数はJSONを組み込みでサポートしています。JavaScriptでXML(特に複数の名前空間を持つ)を処理するのは簡単ではありません。従って、RESTウェブサービスでJSONを使うほうが遥かに簡単です。RESTウェブサービスによるウェブの連携が進むにつれ、これらの技術も一般的になり広く普及しています。

真の違いはなにか

SOAPとRESTの違いを説明する場合、RESTウェブサービスの利点として下記が挙げられるのが一般的です[11]。

  • “軽量–で追加のxmlマークアップがいらない
  • 人間が理解できる出力結果
  • 簡単に構築できる。ツールキットはいらない”

これらの違いは重要です(この記事の後半で詳述します)が、SOAPとRESTの大きな違いは、RESTがHTTPの上に直接実装されているのに対して、SOAPは抽象レイヤ(SOAPメッセージング)を導入している点です。このレイヤはHTTPだけでなく他のトランスポートの上にも実装できます。標準化されているSOAPバインディングは現在のところ、HTTP向け、SMTP向け、JMS向けがありますが、他のトランスポート向けには標準化されていないものがあります。この抽象レイヤはトランスポートとSOAPの実装の疎結合にします。これがSOAPとRESTウェブサービスの根本的な違いです。

この抽象レイヤについての意見は話し相手によって大きく変わります。REST陣営はこのレイヤはやり過ぎであり、本当の価値を提供していないと言います。HTTPはそのままの状態でサービス統合に必要な特徴を備えていると言うのです。一方SOAP陣営はサービス統合(とりわけ企業の)に必要なトランスポートはHTTPだけでなく、しっかりとした昨日豊かなサービス間通信を実現するには移植可能で拡張しやすい[10]抽象レイヤが必要だと主張します。

どちらの考えにもメリットはありますが、私の経験ではSOAの実装をHTTPだけで行うのは実際には上手くいきません。確かに、HTTPは普遍的で、利用するのに追加のインフラ投資は必要ないのが普通です。しかし、HTTPの信頼性は高くありません(HTTP-Rは普及していません)し、, 同期処理(一時的に結合が強まる)しかできません[11]。また、ドランザクションを保証できません。

さらに、HTTPが唯一利用できるトランスポートであるとしても、SOAPエンベロープはメッセージ内のビジネスのデータ(SOAPボディ)とインフラやそれ以外についてのデータ(SOAPヘッダ)をはっきりと区別します。そして、インフラなどのデータが不要な場合は、SOAPエンベロープのオーバヘッドはとても小さくなります。ふたつのタグだけです。しかし、必要になったらそのようなデータをいつでも追加できるようにしっかりと定義された方式を提供してくれます。

つまり、ビジネスとインフラのデータを分離したデータのエンベロープを持つという方式はとても強力です。これはRESTウェブサービスでも使われる方法です。標準的なSOAPを使うか、カスタムのエンベロープスキーマ[12]を使うかは、何を実装するかによって決める必要があります。

その他の違い

SOAPとRESTウェブサービスのよく指摘されるその他の違いについて見てみましょう。

単純さ

RESTはSOAPよりも単純であるというのはよく耳にする意見です。RESTが単純なのは、WSDLやインターフェイス定義が不要だからだという主張はよく聞きます。しかしこのような意見は良く言ってもナイーブです。サービスの利用者と提供者の間の通信に使われる技術はどんなものであれ、やり取りするメッセージの構文や意味(インターフェイス)については合意しなければなりません[13]。RESTでこのような合意をする方法は、ひとつかふたつです。

  • 文書にインターフェイスの定義をまとめ、そのドキュメントに書かれたインターフェイス定義に従って、データのマーシャリング/アンマーシャリングを“手動”でコーディングします。RESTの支持者はこのような方法を推進しますが、10から15を越える要素を含むデータをこの方法で扱うことはほとんどありません。肌理の粗いRESTではそのようなデータは一般的でないからです。さらに、この方法はエラーを起こしやすいのです。多くのフレームワークはこの方法を捨てて、次の方法を利用しています。
  • XSD形式のインターフェイスを定義し、フレームワーク(例えば、XMLのペイロードの場合はJAXBやCastor、JSONペイロードの場合はJackson)を利用してデータのマーシャリング/アンマーシャリングを行います。事実上、この方法はWSDLの最も小さいバージョンであり、SOAPによる実装と同じくらいの労力が必要です。実際、同じ手法がSOAPによる実装でも使われています。単一のインターフェイスとコマンドパターンを使ってサービスを実行するというやり方です。この手法を拡張するとREST用のWSDL2.0 [13]やWADL[14]の使い方と同じになります。

WS*標準[15]が複雑な印象を与えるというのもよく耳にするSOAPに対する不満のひとつです。確かに、主要なWS*標準とそれらの関連を示す単一の仕様は存在しません。しかし、WS*には大多数のサービス間通信で利用できる標準があります。適切なWS*標準を選び、その使い方を理解するには余計な知識/情報が必要ですが、[16]が言うには、

“RESTとSOAの戦いの中で、単純さと標準を比べるのは、馬鹿げています。標準なき単純さはコストやアプリケーションの管理にとっては単に有害なだけです。“

“温度の変換”のような本当に小さなサービスを例外にすれば、RESTがSOAPよりも単純だとは言えません。

軽量

多くのREST支持者がSOAPの代わりにRESTを使う理由は、RESTの場合、リクエストとレスポンスが短くて済むからです。理由は大きく2つあります。

  • SOAPはリクエストとレスポンスにXMLのラッパーが必要です。これによってメッセージのサイズが大きくなります。確かにそうなのかもしれませんが、ラッパーによって付加されるバイト数ではなく、ラッパーによるオーバヘッドの割合について考えるのが重要です。ラッパーのサイズは一定なので、この割合はメッセージのサイズが大きくなるにつれ低下し、最終的には取るに足りないくらい小さくなります。普通、サービスはかなり大雑把にデータのやり取りを行います。従って、リクエストやそれに対する返答はかなり大きいです。それゆえ、SOAPエンベロープのオーバヘッドは問題にはなりません。
  • SOAPはXMLベースのメッセージングであり、冗長なエンコードを行います。一方、RESTはJSON[14]を用いてより軽量なメセージングを実現します。しかし、確かにその通りかもしれませんが、ほとんどのフレームワークでサポートされている、Message Transmission Optimization Mechanism (MTOM)を使えば、メッセージをXMLベースのエンベロープ/ヘッダ/ボディ、その他のコンテンツを含む部分に分割できます。これらの分割された要素は任意のMIMEタイプ、例えば、JSONやバイナリストリームなどにエンコードできます。

確かに理論上はRESTはSOAPより軽量です。しかし、先進的なSOAPの設計技法を使えば、SOAPとRESTのメッセージのサイズの違いを最小限にできます。

簡単に構築できる。ツールキットはいらない

RESTの支持者は、RESTはHTTPベースなので、JavaサーブレットAPIのような馴染みの技術が利用でき、JavaのHTTPは特別なツールキットなしで、RESTサービスとクライアントを実装できると主張します。確かに“手動”で入出力のメッセージやデータマーシャリングを実装したいのならその通りかもしれません。SOAウェブサービスも同じように手動で実装できます。しかし、そんなお決まりなコードを書きたがる人はほとんどいません。SOAPの場合もRESTの場合も何らかのツールきっとを使うのです[18]。

結論

RESTはROA(真のREST)を使って設計する場合やRESTの技術(RESTウェブサービス)を使ってSOAを設計、実装する場合にも使えます。両者とも利点がありますが、企業のビジネスのモデルを使ってビジネスのサービス/リソースを定義するという点は変わりません。SOAとROAをそれぞれ採用した場合、結果として出来上がるもの全く異なります。

著者について

Boris Lublinsky氏はNAVTEQのプリンシパルアーキテクト。大規模データ管理/処理、SOAのアーキテクチャを定義し、NAVTEQの様々なプロジェクトでこれを実装している。InfoQのSOA関連記事の編集者でもあり、OASISで開催されたSOA RAワークショップにも参加している。氏は著書もあり、講演も行っている。最近の書籍は"Applied SOA"。

謝辞

NAVTEQの同僚に感謝します。特に、この記事の執筆を助けてくれたJeffrey Herr、興味深いフィードバック(多くは否定的な)を提供してくれたStefan TilkovとKevin T. Smithに感謝します。おかげで記事を改善できました。

参照

1. Cesare Pautasso、Olaf Zimmermann、Frank Leymann - RESTfulなウェブサービス vs. “巨大”ウェブサービス: アーキテクチャを正しく決める 

2. Boris Lublinsky –アーキテクチャスタイルとしてのSOAを定義する 

3. リソース指向アーキテクチャ

4. Martin Fowlerのリチャードソン成熟モデル: RESTの素晴らしさに向かって 

5. リソース指向アーキテクチャとREST 

6. Dhananjay Nene - サービス指向のRESTアーキテクチャは撞着語法だ 

7. Dhananjay Nene - RESTはインターネットのDBMSだ 

8. Dhananjay Nene - RESTについて 

9. Jørgen Thelin - サービス指向、リソース指向、オブジェクト指向アーキテクチャを比較する 

10. Richard Hubert - Convergent Architecture: Building Model Driven J2EE Systems with UML. Wiley, 2001 ISBN: 0471105600

11. Arun Gandhi - SOAP vs. REST – ベストなウェブサービス 

12. リンク先を参照

13. Lawrence Mandel - WSDL 2.0でRESTウェブサービスを記述する 

14. ウェブアプリケーション記述言語

15. Sanjiva WeerawaranaによるStefan Tilkovへのインタビュー: REST/WS-*の神話を暴く 

16. Lori MacVittie - SOAP vs REST: 単純さと標準の戦い 

17. リンク先を参照 

18. Mark Little - JAX-RS実装の比較


[1] 例えば、[1]の素晴らしい比較

[2] この言葉は技術的には無意味であり、RESTを意味しない。しかし、業界では広く使われており、多くの人がこれをRESTだと思っている

[3]定義によれば、リソースとは直接何かを表現している、アクセス可能かコンポーネントのこと

[4]このようなサービスは“コマンドパターン”で実装されるのが一般的。入力がコマンドそのものと利用されるデータを定義する

[5]異なるメソッドが同じデータを利用し、そのデータがサービスによって公開されているかどうかに関わらず、企業に存在するデータであっても、OOのデータのようにインスタンスに固有のデータではないためメソッドの独立性が保たれる

[6]例えば、[4]はOOとRESTを直接比較して類似点を見ている

[7] RESTの支持者の多くは後者は必要ないと主張する。この点は記事の後半で再度言及する

[8] アーキテクチャスタイルは“システム間の構造と通信の“デザインパターン”のようなものだ'' [9]。より総合的なアーキテクチャスタイルの定義は[10]に書かれている。それによてば“アーキテクチャスタイルとは共通の原則や属性によって結びつくアーキテクチャの仲間のこと”だ

[9]これも人気のある言い方ですが間違っている。定義によれば、ウェブサービスなのはSOAP

[10]WS*の実装はすべてSOAPに依存する。具体的に言えばSOAPヘッダに依存する。

[11]HTTPでの非同期メッセージングは実装可能だが、抽象レイヤが必要だ。例えば、SOAPのWS-Addressing

[12]RESTの支持者の多くはHTTPはすでに標準的なヘッダを持っているのでSOAPヘッダは全く必要ないと主張する。ここで問題なのは、事前に定義されたHTTPヘッダ[12]はしっかりと意味を定義していて、アプリケーション固有の情報を送受信するにはカスタムのヘッダが必要であるということ、そして、それはSOAPヘッダをカスタマイズするのと同じくらい複雑であるということだ

[13]興味深い例として、JAX-RSのクライアントAPIが挙げられる。インターフェイスは事実上Javaのインターフェイスで複数言語のサポートは諦めるしかない

[14] 単純さは常に代償が伴う。例えば、オブジェクト変換を自前で書かずにJSONメッセージにポリモーフィズムを実装してみよ

この記事に星をつける

おすすめ度
スタイル

BT