Webサービス・バージョン管理のベスト・プラクティス

WSDLとUDDIを駆使してWebサービスを最新に合わせる方法

APIのバージョン管理はどの分散システムもが抱く共通の問題であり、残念ながらWebサービスも例外ではありません。この記事では、Kyle Brown と Michael EllisはWebサービス開発者が直面するバージョン管理問題の範囲の概要を明確にし、テンプレートとなる解決法をいくつか提供し、問題に取り組むうえでのベスト・プラクティスとアーキテクチャーを考察します。

Kyle Brown, Senior Technical Staff Member, IBM

Kyle BrownはIBM WebSphere Servicesの上級テクニカル・スタッフ・メンバーです。Fortune 500のクライアントに対して、オブジェクト指向プログラミングやJava 2 Enterprise Edition (J2EE) テクノロジーに関するコンサルティングおよび指導を行っています。『Enterprise Java Programming with IBM WebSphere』、『WebSphere 4.0 AEs Workbook for Enterprise JavaBeans (3rd Edition)』、および『The Design Patterns Smalltalk Companion』の著者の1人です。Enterprise Java、OOデザイン、およびデザイン・パターンに関する講演の経験があります。連絡先は、brownkyl@us.ibm.com です。



2004年 1月 30日

正しいAPIバージョン管理は、分散システム開発者が直面する最も難しい課題のひとつとされてきました。CORBAによるレッセフェール(自由放任)なアプローチからDCOMによる厳格なスキームまで、様々な方法が提案されてきました。Webサービスの到来により、その問題を軽減するうえで活用できる機能がいくつか入手可能になりました。しかし、Webサービスのアーキテクチャーにバージョン管理が組み込まれていないのが厳しい現実です。IBMや他のベンダーからの最新版の製品は直接バージョン管理の課題に取り組みませんので、開発者がベスト・プラクティスとパターンの適用をとおして問題に対処することになります。

WebサービスのAPIバージョン管理の問題を理解するのは簡単です。フラグメントを使用して定義されたWSDLオペレーション(operation)を含む単純なWSDL文書があると想定してください(リスト1)。(このオペレーションはWSDL仕様の例から派生しています。参考文献を参照してください。)

リスト1. GetLastTradePrice WSDL
<types>
       <schema targetNamespace="http://example.com/stockquote.xsd"
  xmlns="http://www.w3.org/2000/10/XMLSchema">
           <element name="TradePriceRequest">
              <complexType>
                  <all>
                      <element name="tickerSymbol" type="string"/>
                  </all>
              </complexType>
           </element>
           <element name="TradePriceResponse">
              <complexType>
                  <all>
                      <element name="price" type="float"/>
                  </all>
              </complexType>
           </element>
       </schema>
    </types>

    <message name="GetTradePriceInput">
        <part name="tickerSymbol"
 element="xsd1:TradePriceRequest"/>
    </message>
    <message name="GetTradePriceOutput">
        <part name="result" element="xsd1:TradePriceResponse "/>
    </message>
    <portType name="StockQuotePortType">
        <operation name="GetLastTradePrice">
           <input message="tns:GetTradePriceInput"/>
           <output message="tns:GetTradePriceOutput"/>
        </operation>
    </portType>

Webサービスを配置して、いくらかのリクエスターがそれを利用して作成されたとします。しかしながら、コードを検討する段階で、浮動小数点がドルの値を表記するには最適ではないということに気付かれることでしょう。なにしろ、$2.33はあっても、$2.33333333333などという値段はあり得ないのですから。システムで卸値が計算される方法が原因で、蓄積を続ける四捨五入の誤差がアップストリームの問題を発生させます。その結果、返されるドルの値はときどき間違うことにもなります。(ドルではなく)セントを整数で表記することを頭に入れ、浮動小数点から整数にデータ・タイプを変換する必要があります。リスト2にて示されるとおりに、スキーマへの変更を(少なくとも)1つ施すだけで、この変更を実装できるのです。

リスト2. アップデートされたTradePriceResponse WSDL
<element name="TradePriceResponse">
   <complexType>
      <all>
         <element name="price" type="integer"/>
      </all>
   </complexType>
</element>

しかし、ここで新たな問題に直面します。浮動小数点を予測している現存のリクエスター全てが整数を受信したらどうなるのでしょうか?これは些細な問題としては最悪の例です。予測とは別の解答なのが明白なのにもかかわらず、SOAPエンベロープ内に出力されたXMLに対しリクエスターが処理を続行することを意味します。この場合、リクエスターは予想された解答の百倍の値(小数点なし)を受信することになるのです。

(WSDLの場合)Webサービスの定義には、リクエスターにその相違点を伝える明確なものが何もありません。仮に開発者が上記の問題に変更を加えても、旧リクエスターは実行に失敗し、その失敗はWebサービス・インフラストラクチャーでは発見不可能となるのです。現存するリクエスターを中断する(そしてしない)WSDLの変更の種類を注意深く明確にする必要があります。現存するリクエスターを中断するほどにWSDLが変更される場合、以前からのリクエスターが変更されたWebサービスを呼び出さないことを確証する仕組みが必要とされます。

変更タイプを理解する

大雑把に言えば、WSDL文書の変更には、現存するリクエスターを中断しないタイプと中断するタイプの2種類あります。標準的な業界用語に従うかたちで、前者を「後方互換の変更」(backwards-compatible change)そして後者を「非後方互換の変更」(non-backwards-compatible change)とします。後方互換の変更のタイプを以下に記します。

  • 現存するWSDL文書に新規のWSDLオペレーションを追加。現存するリクエスターが新規のオペレーションに気付かなければ、リクエスターはその導入に影響されません。
  • 以前に存在したタイプに含まれないWSDL文書にXMLスキーマ・タイプを追加。以前に存在したどのタイプ(構文解析コードの修正を必要とする)にもそれらのデータ・タイプが含まれていないのであれば、新規の複素数データ・タイプを新規のオペレーションが必要としていても、現存のリクエスターにその類の変更は影響を及ぼしません。

しかしながら、以下に示す様な後方互換性の無い変更タイプも数多くあります。

  • オペレーションの除去
  • オペレーションの名前変更
  • オペレーションのパラメーター変更(データ・タイプまたは順序)
  • 複素数データ・タイプの構造変更

広い意味で、2つの異なる手法を活用すれば、異なるタイプの変更に対処できるわけなのです。

後方互換の変更には、WSDL文書は単に(リクエスターがWSDL文書を取得するときに使う)リポジトリーにてアップデートされ、現存のWebサービスがアップデートされます。全てのWSDL文書の最新版がバージョン管理システムに保管され、固有のバージョンIDまたはバージョン・ヒストリーを示すためにXMLコメントを使用することを推奨します。しかしながら、それは純粋にWebサービス・プロバイダーの利便性のためのものであり、Webサービス・リクエスターの実装者に必須ではありません。

非後方互換の変更には、別のアプローチを採用すべきです。この問題を解決するには、互換性のあるドキュメントのバージョンを明確にするために、XML名前空間から始めましょう。この仕組みは、WSDLにてSOAPバインディングがリテラル・エンコード方式かSOAPエンコード方式のどちらを使ったかで決まります。リテラル・エンコードでは、XMLスキーマの名前空間の定義の一部としてのメッセージ定義内で名前空間が指定されます。SOAPエンコード方式では、SOAPバインディング要素の中で名前空間は指定されます。選択された仕組みに関係なく、指定された名前空間の値は全てのSOAPメッセージと結果と共に送信されます。これにより、Webサービスの実装は着信中のメッセージにどう正しく対処するかの判断を、名前空間の値を基にできるようになります。

非後方互換の変更がWSDL文書に施されなければならない場合、そのドキュメントから派生するXMLエレメントの名前空間が固有であることを保証するのが第一歩です。様々な種類のWSDL文書が固有であるのを確証するには、名前空間の定義の終わりに日付またはバージョン・スタンプを追加する簡単な名付けスキームを推奨します。これはXML名前空間の定義に向けたW3Cの総合ガイドラインに追従します。リテラル用途のパラメーターを使用していると想定すれば、ここまでで論議されてきたサンプルWSDL内のXMLタイプの定義は以下のようになります。

リスト3. 固有の名前空間付きのアップデートされたWSDL
<types>
       <schema targetNamespace="http://example.com/2003/10/15/stockquote.xsd"
              xmlns="http://www.w3.org/2000/10/XMLSchema">
           <element name="TradePriceRequest">
              <complexType>
                  <all>
                      <element name="tickerSymbol" type="string"/>
                  </all>
              </complexType>
           </element>
           <element name="TradePriceResponse">
              <complexType>
                  <all>
                      <element name="price" type="float"/>
                  </all>
              </complexType>
           </element>
       </schema>
    </types>

名前空間を以下の値に再定義したことに注目してください。

http://example.com/2003/10/15/stockquote.xsd

この例で示される名付けの慣例は、W3Cがスキーマを認識する上で使われる標準的な慣例を基にしています。会社名に続いて日付スタンプ、そしてそれに続いて特定の名前空間を(意味的にそして明確に)示す1つ(かそれ以上)の識別子から成ります。ここでは最も一般的なアプローチから離れます。大半のW3C名前空間には、会社名の後には年(year)と月(month)を示す部分しかありません。変更が月に一度以上発生する可能性を考慮し、ある特定の月(month)の日(day)を示す部分を名前空間に追加することをお奨めします。

名前空間の変更を決断した後には、旧リクエスターをどうするかを考える必要があります。一つの方法としましては、旧名前空間へのリクエストを受信したときに、サーバー・エンドにてわざと失敗を生成します。別の一般的なこの問題への対処法として、どの特定の名前空間にも入るWebサービス要求にどう対処するかを判断する中継機器(例えば、ルーター)の使用が挙げられます。ルーターは、名前空間の日付スタンプを調べ、旧名前空間からの要求を旧バージョンのWebサービスに、そして新しい名前空間からの要求を新バージョンのWebサービスに経路を定めます。しかしながら、このアプローチには短所があります。その一つとして、まずルーターをただちに実装しなくてはなりません(TalkingBlocksのように、それをすぐに実現できる製品もあるにはあるのですが)。もっと重要だと思われますが、少なくとも新規のWSDLに全ての旧リクエスターが移行するまでの遷移期間中は、それぞれのWebサービスを二度配置しなくてはなりません。


サービス・バージョン管理対サービス・バインディング

バージョン管理の課題をより深く考察するには、2つの質問を投げ掛けるのも手です。

  • Webサービスの用語では、インターフェースのバージョンは何でしょう?
  • 個別のインターフェース・バージョンそして完全に別個のインターフェースの間にある相違点は重要なのでしょうか?

非後方互換的な変更がサービスへのインターフェースに施されれば、実質的には完全に新規のサービスが作成されることになると解釈できます。そのような場合、最初のインターフェースの実装が継続するのでなければ、以前に存在していたサービスは事実上停止します。クライアントの観点からは、そのサービスはインターフェースそして(それが保持すると主張する)非機能的な資質(例:trust属性、QoS属性)以上の何物でもありません。かくして、サービスへのインターフェースが非後方互換的に変更されれば、それはもはや元のサービスのインスタンスを表さず、むしろ完全に新しいサービスと言えましょう。

この観点から見れば、インターフェースのバージョンは常に先在するインターフェースに対して後方互換性を抱きます。以前のオペレーション全てが保たれる間に新たなオペレーションが追加されたか、または元のインターフェースとの互換性を抱くように現存するオペレーションのシグニチャーが変更されたことをそれは意味します(そのような変更の機会は限られます)。さらに、旧式バージョンのサービスが新型バージョンのサービスに対して前方互換性を抱かないと考えるのが妥当です。その結果、サービス・インターフェースが後方互換ではない方法で変更されれば、それは、旧サービスの新バージョンではなく、それは新規のサービスなのです。

既に述べられたとおりですが、固有の名前空間でそれぞれのサービス・インターフェースを識別すれば、それぞれを別個のものに仕上げられます。後方互換性はそれぞれのバージョンに必須なので、同一インターフェースでの新旧バージョンを識別する方法も必要です。バージョンを表記する最良の手段を理解するには、バインディングの仕組みを把握することが必要です。これにはすぐに触れますので、しばしのお待ちを。

2つ目の質問:「個別のインターフェース・バージョンそして完全に別個のインターフェースの間にある相違点は重要なのでしょうか?」の解答は「はい」です。バインディングの仕組みは互換性のあるインターフェースを(互換性の無いインターフェースに対して)認識する必要がありますし、バインダーが求める名前空間の中にて共通のコンポーネントを(クライアントのそれと同等かより新しいバージョン識別子と共に)互換性のあるインターフェースが提供するからです。


サービス・バインディング

サービスに対する見解を受け入れると同時に、次の質問が自然と浮かび上がります。(バインディングを中断せずにサービスに対してバージョン管理を施すように)クライアントをサービスにバインドするには、どのアプローチが良いのでしょうか?サービスのバージョン管理を簡略化するためにも、インターフェースの不安定な性質(アスペクト)へのクライアント側の組み合わせを全て排除すべきです。変更される性質は、以下のとおりです。

  • サービス・インターフェースに供給される特定のオペレーションのセット。
  • サービス用WSDLのURI。
  • サービス・インターフェースのバージョン番号。
  • サービス・エンドポイント。

サービス・プロバイダーの配置の要求に合わせるために、サービス・エンドポイントはいつ変更してもおかしくありません。一般的には、バインディングの仕組みは静的なエンドポイントを想定しません。

この時点で、バインディングのアプローチの重要な要素がすでに形を成しています。バインディングへの柔軟なアプローチは

  • サービス・エンドポイントを間接的に入手する。
  • どの(互換性のあるインターフェース外の)サービスの性質も静的であると勝手に想定しない。
  • (サービス内の)インターフェース・バージョンそしてインターフェース(そのもの)を基に互換性のあるサービスを識別する。

『バージョンを認識するサービス登録』として、UDDIを使用する

UDDIとWSDLの連携使用に関連するベスト・プラクティスが発達を遂げています。(それらの基準との互換性と整合性をサービスが通知できるように)基準のWebサービス・インターフェースを公開する必要性から、ベスト・プラクティスは成り立っています。

この時点では、奨励されたベスト・プラクティスは1つのインターフェース・バージョンのみに特化され、サービス・バージョン管理には採用されません。しかしながら、UDDIのデータ・モデルは懐が深いので、サービス・バージョン管理を含むように最新のベスト・プラクティスを拡張できます。

最新のベスト・プラクティスは、与えられたwsdl:portTypeのバージョンが固有のtModelに象徴されることを前提としております。そのportTypeバージョンのクライアントは、そのtModel と連携することにより整合性を通知するサービスへのUDDIをGreen Page検索(ユニークキーでの簡単な検索)できます。この関係は(UDDI version 2を基にした)図1にて示されています。

図1. WSDLのサービスとの関連付け
図1. WSDLのサービスとの関連付け

ベスト・プラクティスの用途はtModelKeyとの的確な組み合わせをほのめかし、ベスト・プラクティスは異なるインターフェースが異なるtModelsを抱くことを必要とします。そのような理由から、現行のベスト・プラクティスでは、そのような検索の結果は後続のインターフェース・バージョンに互換性のあるサービスを含みません。

UDDIバージョン管理のアプローチその1:複数のインターフェースとの整合性を通知する

しかしながら、与えられたサービスが通知するインターフェースの数を制限するものは、ベスト・プラクティス(またはデータ・モデル)にはありません。ベスト・プラクティスに従う形では、tModelInstanceDetailsのコレクションの中で、インターフェースの前後両方のバージョンに互換性のあるサービスはそれぞれのtModelを参照できます。

このアプローチの長所は

  • バージョン番号の必要性を排除します。
  • Green Page照会が実行される手法を直す必要がありません。

しかしながら、このアプローチには短所もあります。

  • インターフェースが複数のバージョンをとおして移行すれば、バージョンコレクションの管理はわずらわしくなります。
  • 複数のサービス実装が存在すれば、複数のtModelコレクションが管理されることになります。

UDDIバージョン管理のアプローチその2:インターフェースtModelを限定するバージョン番号を導入する

ベスト・プラクティスによれば、基準のインターフェースtModelsへのリファレンスを作成するために、tModelInstanceInfosと呼ばれる構造をUDDIのbindingTemplatesは使用します。TModelInstanceInfoの構造は、instanceDetails構造のセット(下記にて定義)を随意に含みます。

リスト4. UDDI instanceDetails用のXSD
<xsd:complexType name="instanceDetails">
   <xsd:sequence>
      <xsd:element ref="uddi:description" minOccurs="0" maxOccurs="unbounded"/>
           <xsd:element ref="uddi:overviewDoc" minOccurs="0"/>
           <xsd:element ref="uddi:instanceParms" minOccurs="0"/>
     </xsd:sequence>
</xsd:complexType>>

UDDI仕様からの引用です。「サービス記述のtModelに特化したコンポーネントを説明するか、追加の技術的なデータ・サポートを必要とするサービスをサポートするために、tModelのリファレンスに特化した設定または別の記述された情報が必要とされるときに、そのエレメントは使用されます。」この記事での場合、『リファレンスに特化した設定』とは、インターフェースtModelのバージョン番号のことです。

インターフェースのバージョンを考慮するためにGreen Page検索を変更しInstanceDetails内にバージョン番号を導入することにより、Green Page照会はバージョンを把握します。

しかしながら、それ自身のバージョン番号だけでは不十分です。整合性を主張するサービスの全てが共通のWSDL定義を抱くという前提で、インターフェースtModelとインターフェースWSDLを現行のUDDIベスト・プラクティスは結びつけます。バージョン管理されたサービス・インターフェースは共通の定義を共有しませんので、インターフェースのバージョン管理の状況においてはその前提は有効ではありません。我々が求めているのは、WSDLをサービスtModelから切り離してそれをインターフェース・バージョン番号と関連付けることです。

(上記で参照された)InstanceDetails構造内のoverviewDocURL値をインターフェースWSDLの位置に設定することにより、必須の関連は達成されます。バージョン番号とWSDL URLは、bindingTemplateと基準のtModelの間のリファレンスのリンク属性として扱われます。これら2つの最新ベスト・プラクティスへの変更は、UDDIのインターフェース・バージョン管理を達成する手段を提供します。

要約:UDDIのWebサービスの公開されたインターフェースを限定するバージョン番号を使用するには、バージョン番号を保有するinstanceDetails構造そして関連するWSDL文書のURLが、(基準のサービス・タイプの最新UDDIベスト・プラクティスに必須とされる基準のtModelリファレンスの)tModelInstanceInfoに導入されることが必要です。

このアプローチには重要な利点が1つあります。

  • (互換性を抱く)インターフェース・バージョン全てへのtModelリファレンスを運用するサービス登録を必要とせずとも、サービス・バージョン管理は達成されます。

しかしながら、いくつかの欠点も見受けられます。

  • 総合的に、サービス・インターフェースの進化の過程で、全てのサービス実装はバージョン番号と一致しなくてはなりません。バージョン番号は複数の実装の間で共有される構造内に存在しないからです。とあるサービスが特定のインターフェースをバージョンnとして登録する間に、別のサービスが同じインターフェースをバージョンmとして通知するという事態にもなりかねません。
  • 典型的なGreen Page照会を実行する上で必要なステップは、instanceDetails構造内のバージョン識別子への考慮を含むように変更されるべきです。
  • このアプローチは、OASISにより公開されているベスト・プラクティスと対立します。

どちらのUDDIバージョン管理方法を採用すべきか?

2つ目のアプローチは様々な問題をはらみますので、ほとんどの場合においては最初のアプローチを採用すべきです。

  • 公開されたベスト・プラクティスに矛盾するUDDI Green Page照会を、全てのクライアントが採用しなくてはなりません。
  • インターフェースに関連するバージョン番号が全ての実装に一貫して使われない可能性もあります。
  • サービス登録の必須条件はさらに複雑です。

性能の観点から述べますと、tModelキー以上の何物も使わずとも最初のアプローチはバージョン互換性を抱くサーチをサポートします。2つ目のアプローチは複数のUDDI構造を分析する照会を必要とし、その処理は照会を遅らせます。


まとめ

この記事では、Webサービスでのサービス・バージョン管理に対処する最も一般的なテクニックの一部を考察しました。選択されたアプローチは複数の要素に依存しますが、ほとんどの問題を解決する効果的な解決法を探すには十分な数のオプションがあります。特に、問題を軽減するために、UDDIのバージョン番号の使用のみならず固有のバージョン・名前空間の採用をも考察しました。それぞれの環境に最適なテクニックを判断する材料として、長所と短所のリストを活用するのも手です。

参考文献

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=SOA and web services
ArticleID=245537
ArticleTitle=Webサービス・バージョン管理のベスト・プラクティス
publish-date=01302004