DatawireがオープンソースのDatawire Connectフレームワークをリリースした。Java, Python, あるいはNodeJSで記述されたサービスを対象に,自動生成されるRPCスタイルのクライアントライブラリを使用した‘レジリエントなマイクロサービス接続’を実現する。クライアントライブラリでは,サービス登録やディスカバリ,ダイナミックなロードバランシングとルーティング,自動タイムアウト,サーキットブレーカなどの機能を提供する。
Datawire Connectは,サービス間のコントラクト記述用に設計された言語であるQuarkを使って構築されている。QuarkはThriftやAvro,gRPCといった従来のIDLと同じような,サービスAPIやデータのシリアライズ方法の定義に加えて,IDLによる記述を拡張することで,プロトコルの動作をサービスコントラクトの一部として記述することも可能になっている。例えば,サーキットブレーカやリトライのセマンティクス,あるいはバックプレッシャを追加して,サービスの動作が遅い場合にクライアントがどのように動作するのかを定義することにより,パフォーマンスの向上が実現する。
InfoQでは,DatawireのCTOでチーフアーキテクトのRafeal Schloming氏と話す機会を得て,分散システム構築の難しさ,現在のマイクロサービスのツーリング,‘よい’サービスコントラクトあるいはAPIの条件,従来型アーキテクチャからマイクロサービスへのマイグレーションの実情などについて聞くことができた。
InfoQ: こんにちはRafaelさん,今日はお時間を頂いてありがとうございます。先日のプレゼンテーションであなたは,問題の性質に関わらず,システムはますます‘分散化’していく,と話されていましたが,これについてもう少し詳しく説明して頂けますか?
Schloming: SaaS(サービス・アズ・ア・システム)は,継続的な稼働と運用規模に関する要請に応えるべく,古典的な分散システムをメインストリームに引き出しました。しかしながら現在のSaaSビジネスは,機能面での深さ,広さ,開発やイノベーションの速度を競うようになっています。これにより,それまでとは“違う”種類の分散システムが登場したのです。
開発速度を上げるには,多数の開発者が必要になります。そうして数の増えた開発者たちが,同じ問題領域内で互いに干渉することなく作業を進めるためには,すべての開発が独立的に行なわれる必要があります。例えば連続稼働する分散アプリケーションを分散開発する場合のように,大規模なアプリケーションを構成する小さなサービス群を,数十から数百のチームがそれぞれアップデートするというのは,まさにこの方法なのです。
この方法では,問題領域が組織構造に大きく影響されるのと同じように,アプリケーションを分散する方法にも人的要因が深く関わってきます。連続稼働する分散システムについては,Conwayの法則の適用を検討するべきでしょう。
この種の分散システムをサポートするために必要なツーリングは,従来の分散システムで必要なものとはかなり違います。“違う種類の分散システム”と私が言ったのは,このような理由からです。
InfoQ: 分散開発はどのように難しいのでしょう?クロスファンクショナルチームの出現は解決策になるのでしょうか?ある種の問題を解決する上で,コロケーションは必須なのでしょうか?
Schloming: 分散開発は確かに難題ですが,不可避でもあります。ですから私としては,“どうやって分散開発を実施するか”について答えたいと思います。
コロケーションは真の解答にはなりません。ある程度の規模を持った企業ならば,全員が同じオフィス内で働いていても,分散開発を行なっているはずです。数百人のエンジニアが同じ部屋で作業している場合,お互いが何をしているのかをすべて理解することはできませんから,分散開発は必然になります。
分散開発は,問題を小さく分割することが可能で,それぞれが疎結合のインターフェースを持つ場合に最も効果的だと思われます。分散型チーム(あるいはどのようなチームでも)において,チーム間のコミュニケーションのバウンダリを形成するのはAPIです。ですから,ひとつのコンポーネントの変更が他に影響する場合が多ければ,たくさんのチームが相互にコミュニケーションを取る必要がありますから,分散型開発は立ち行かなくなります。
クロスファンクショナルなチームの登場については,解決策ではなく,チームが分散開発に成功した結果だ,と私は見ています。全体に対して明確に定められたインターフェースを持った,自己完結した部分に責任を分散することは,開発組織を拡大する上では極めて有効な手段です。そして,これをSaaS企業というコンテキストで行なうことは,エンドユーザにサービスを提供する最終責任の委譲と切り離して考えることはできないのです。これを実践するならば,担当チームは,その目標を達成するために必要なスキルを,クロスファンクショナルに持たざるを得なくなります。
InfoQ: マイクロサービスのツーリングの現状について,コメントをお願いします。今後12ヶ月間で,どのようなことが起きると思いますか?
Schloming: マイクロサービスに関するツーリングは,ごく初期的な段階にあります。いくつかの判断基準から見るならば,存在しないと言っても過言ではありません。このように言うのは,マイクロサービスを成功させる上で,ラインアップしなくてはならないものの数が非常に多いからです。サービスディスカバリやサービスルーティングが必要ですし,何種類かのデプロイメントパイプラインも必要です。従来のテストのカテゴリ(ユニット,機能,統合)に相当する新しいテスト方法論や,何千というサービスやインスタンスの状況を監視するインスペクションツールも用意しなくてはなりません。ロギングや監視に関するソリューションも必要です。
多くの人が多数のパーツを作るのですから,‘これだけやれば大丈夫’というソリューションはここでは存在しません。エンド・ツー・エンドのマイクロサービスプラットフォームは,資金の潤沢な大規模組織であっても,現時点ではまだ野心的なDIY活動なのです。アーリーアダプタ企業が提供しているスタックを適用する場合であっても,こういったすべてのカテゴリのツールが非常に断片化されているので,エンジニアが全体をまとめる作業はやはり必要なのです。
このような断片化の状況を踏まえて,私たちDatawireでは,マイクロサービス用のツールとしては唯一の統合化セットだと考えるものを開発しています。当社のオープンソースプロダクトであるDatawire Connectの目標は,企業がマイクロサービスに着手する上で必要なツールをすべて提供することによって,25人規模のチームが専任で,マイクロサービスのインフラストラクチャ全体をスクラッチから開発する必要をなくすことにあります。
InfoQ: 昨年はたくさんの講演で,サービスのバウンダリとコンストラクトの定義の重要性が取り上げられていましたが,‘スキーマ先行’を提唱する人もいれば,利用者ベースの進化的な展開が最善とする人もいます。あなたの意見を教えてください。
Schloming: どちらか一方,というものではないと思います。理解しなくてはならないのは,独立したソフトウェアコンポーネントが接続される場合,通常は2つの異なるチームが存在する,ということです。一方がビジネスチームで他方がユーザである場合でも,あるいは2つのチームが同じビジネス内で作業している場合であっても,これは事実です。このダイナミクスは結果として,複数チームが関係するインターフェースの変更を,非常に高価で時間を要するものにします。この部分を変更するには,チーム間のコミュニケーションの完了を待たなくてはならないからです。多数のチームがインターフェースを使用している場合では,変更に数年を要することもあり得ます。
このため,サービスのインターフェース領域が何であるかを確実に理解しておくことは重要です。何か特定のツールを使用しなければならない,あるいは設計委員会を何ヶ月も開催して,完璧なバウンダリを事前に設計しておかなくてはならない,ということではありません。最小限の利用者ベースのコントラクトから着手すること,それを明確に表現する方法(形式的なスキーマや,もっとアドホックな手段を用いて)を確立しておくこと,この2つはいずれも価値のある,非常に望ましいプラクティスです。
InfoQ: 優れたサービスコントラクトとはどんなものでしょう?それをコードで実現するには,どのような方法が最善なのでしょうか?
Schloming: 一般論で言うのは非常に難しい問題ですね。開発方法論としてマイクロサービスを採用する場合,抽象化の単位はサービスです。従来のプログラムで言えば,クラスあるいは関数に近いものです。“よい関数とは何か”,“よいクラスとは何か”という疑問を考えてみれば,回答の難しさが分かると思います。
このような質問に対しては,否定論的に,ネガティブに答えるのが一般的です。良いクラス,あるいは関数はどうあってはならないのか,といったようにです。 大きすぎない,複雑過ぎない,など。サービスのコントラクトについても,これと同じことが言えます。緊密に結合されないことは,求められる価値があります。適切に設計されたAPIは一般的にそうですが,サービスにおいてはさらに重要です。さらに,明示的でなくてはなりません。コントラクトが曖昧すぎると,それが破られたことに気付かず,結果的にバグの互換性を維持するのに苦心することにもなりかねません。
サービスコントラクトを実装する最善の方法については,これから検討する余地が十分に残っていると思います。コントラクト関連のツーリングのほとんどは,行動的(behavial)コントラクトではなく,構造的(structural)コントラクトを重視しています。ですが,分散アプリケーションの開発においては,行動的コントラクトの重要性がますます高くなっています。私の知る限りでは,Datawire Connectは,行動的コントラクトを表現するために,最善の方法を提供するツーリングを開発している唯一のプロジェクトです。ただし,他のプロジェクトから学ぶことも忘れていません!
優れたサービスコントラクトを構築する上で最も重要な要素は,それを明示的に捉えるための手段を,実装の*外部*に*いくつか*用意しておくことだと思います。スキーマツールやテストスイートを使うにせよ,あるいは単にドキュメント化するにせよ,これを行なわないことの危険性は,実装の詳細によって暗黙のうちにコントラクトが決定されてしまう点にあります。このようなコントラクトは,維持するために大きな手間を要するからです。
InfoQ: 企業(おそらくは旧式のSOAを採用している)で働く開発者が,マイクロサービスの開発や関連するエコシステムに移行するには,どのような点が困難なのでしょうか?
Schloming: 困難なポイントは2つあります。別々に考えた方がよいでしょう。ひとつはツーリングがまだ初期の段階であるため,一般論として学習曲線が急である点です。もっとも,ツーリングの状況は時間とともに改善されていくでしょうし,マイクロサービス環境の生産性を改善する上で,必ずしもすべての開発者がすべてのツーリングに精通する必要はありませんから,はさほど大きな障害ではありません。
それよりも大きな問題は,世界に対する新たなメンタルモデルを必要とすることです。 それほど数の多くないマイクロサービスを開発する場合でも,もしも一般的なエンタープライズSOAと同じようなライブラリや,粒度の大きなサービスを使用するならば,とんでもなく脆弱なシステムが出来上がることになるでしょう。
その理由は,従来型のプログラミングやエンタープライズSOAの根底に,複合的なアプリケーションを機能させるにはすべてのコンポーネントが機能しなくてはならない,という仮定が存在するからです。いわば昔のクリスマスツリーの照明のようなものです。ひとつひとつの電球がマイクロサービスで,それを一列につなぐのだとすれば,ひとつでも電球が切れれば一本分の照明がすべて点灯しなくなります。それだけではありません。電球が切れる瞬間を注意深く観察しない限り,どの電球がだめなのかを見つけ出して,全体をもう一度点くようにするのは大変なことなのです。
マイクロサービスでは,利用するコンポーネントはすべて,あなたがまったくコントロールできない方法で頻繁にアップデートされます。それが問題を引き起こすのです。ですから「電球」をできるかぎり並列につないでおく必要があります。これならば,ひとつが使用不能になった場合でも,確実に,簡単かつ迅速に対処できます。
このためには,システム構築方法についてのメンタルモデルを根本的に変える必要があります。まずはタイムアウトやクライアント側のロードバランス,サーキットブレーカといったものから始めますが,それだけではありません。これらのサービスがダウンしている場合でもアクセスに使用するクライアントがハングしないならば,それはそれで素晴らしいのですが,そのような場合にnullやデフォルト値を返して,その値が原因でエラーを吐くようであれば,結局は脆弱なシステムだ,ということになります。
マイクロサービスの開発者としては,外部の障害に可能な限り影響されないためにはどうすればよいかを考える必要があります。この種のシステムを始めて手掛ける開発者にとって,これが最も難しい部分のひとつだと思います。
オープンソースのDatawire Connectフレームワークに関する詳細な情報は,同プロジェクトのGitHubリポジトリ,Datawireブログの発表記事などで確認することができる。
この記事を評価
- 編集者評
- 編集長対応