目次


マイクロサービス入門

より小さく、より速く、より強力に: より優れたクラウド・アプリケーションを土台から築き上げる

Comments

2014年の初めから 2015年にかけて、マイクロサービスは新しくてホットなバズワードとなり、人々の注目を瞬く間にクラウドから奪い取りました。このチュートリアルでは、マイクロサービスの歴史を一通り説明し、マイクロサービス・アーキテクチャーに基づいてアプリケーションを構築することの意味を明らかにします。

Netflix のストリーミング: のちに普及することとなったマイクロサービスの誕生

皆さんの中には、マイクロサービスについて知っている方もいれば、知らない方もいるかもしれませんが、Netflix については耳にしたことがあるはずです。さらに、Netflix はクラウド・インフラストラクチャーを管理するためのソフトウェアの作成およびリリースで成功を収めたことから、NOSS (Netflix Open Source Software) という言葉についても聞き覚えがあることでしょう。NOSS は Netflix デジタル・エンターテイメイト・ストリーミング帝国の原動力となっているソフトウェアです。

Netflix は 2009年ごろから、アプリケーションの開発モデルと運用モデルを全面的に定義しなおす作業を始めました ― この作業は、後にマイクロサービスとして知られるようになったモデルの最初の波に乗って、完全に API 駆動で行われました。その当時は、業界の傍観者たちから「正気を失っている!」、「Netflix ではうまくいったとしても、他では実現不可能だ」などと冷笑されていましたが、時を 2013年に移すと、そのような傍観者のほとんどが「マイクロサービスを採用する方向で進めている」といった方向へと態度を変えました。Google で「microservices」を検索すると、525,000 件を超える結果が得られることから、この概念が間違いなく有効であり、強力であることが示されています。

しかし、そもそもマイクロサービスとは何なのでしょう?マイクロサービスをベースとしたアーキテクチャーとはどのようなものなのでしょう?図 1 に、旅行予約サービスに関するマイクロサービスの概念図を示します。図中の 7 つのタイルのそれぞれが、個別のマイクロサービスを表します。これらのタイルは、どのマイクロサービスが他のマイクロサービスと相互作用して、内部アプリケーションと外部向けアプリケーションの両方に必要な機能を提供するのかがわかるように並べられています。各サービスの高さは、他のサービスとの関連でそれぞれのサービスがどれぐらい使用されているか、その量を表しています。皆さんが独自のマイクロサービス・アーキテクチャーを表現する方法を理解できるよう、この記事の全体を通して、マイクロサービスの基礎を抑えていきます。

図 1. マイクロサービスの概念図
命名規則と相互作用の原則が定義されたマイクロサービスの概念的視点を示す図
命名規則と相互作用の原則が定義されたマイクロサービスの概念的視点を示す図

マイクロサービスがどのような形で始まったのかについての詳しい説明は、Martin Fowler 氏の優れたブログ投稿を読んでください。この記事で私が紹介したいのは、そのブログ投稿の要点と、皆さんの現在の環境へのマイクロサービスの適用について、さらにはそれを実現する方法についてです。

あるカンファレンスの講演で、以前 Netflix に勤めていた Adrian Cockcroft 氏は、マイクロサービスを「粒度の細かい SOA (Service-Oriented Architecture)」として定義しました。この (10 年以上前に考え出されたアーキテクチャー・スタイルである) SOA については、頭字語に使われている言葉さえ知っていれば、その内容を詳しく知っている必要はありません。開発初日からサービスを組み合わせてアーキテクチャー全体を構築できれば理想的ですが、マイクロサービスでは、これらのサービスのそれぞれに、他のサービスへの副次作用がない単独の目的を持たせ、アーキテクチャー全体を専門に取り組むエンジニアの数をより少なく抑えた上で、より大規模なアーキテクチャーに対処できるようにします。

マイクロサービスと、これに関連するアーキテクチャーを定義するために、私は最近のスポーツ選手を表現するために使われている「bigger, faster, stronger (より大きく、より速く、より強く)」というフレーズをもじって、「smaller, faster, stronger (より小さく、より迅速に、より強力に)」というフレーズを使っています (図 2 を参照)。マイクロサービスとは基本的に、より迅速 (faster) に構築して提供できる、単独でも全体としても、より強力 (stronger) になった、より小さい (smaller) アーキテクチャー・コンポーネントが多数集まったものです。

図 2. マイクロサービス: smaller, faster, stronger (より小さく、より迅速に、より強力に)
マイクロサービスの 3 つの主要原則「smaller, faster, stronger (より小さく、より迅速に、より強力に)」を示す図
マイクロサービスの 3 つの主要原則「smaller, faster, stronger (より小さく、より迅速に、より強力に)」を示す図

smaller ― より小さく

マイクロサービスは、モノリス (つまり、モノリシック) の終焉を意味します。モノリスは、図 3 に示す「厳かなモノリス」のように、大きく、不恰好で、動きが遅く、非効率的です。私たちは、WAR ファイルのサイズが 2 GB にもなるという世界から抜け出し (2 GB というのは、WAR ファイル単独のサイズです。アプリケーション・サーバーやオペレーティング・システムのコンポーネントではありません。)、アプリケーション、サーバー、必要なオペレーティング・システムといった、すべてのコンポーネントが揃った 500 MB ほどのサービスを数多く組み合わせて構成される世界へと向かっています。

図 3. 厳かなモノリス
従来の非生産的なアプリケーション開発手法を象徴するカード「厳かなモノリス」の画像

メインフレームからクライアント/サーバー・アーキテクチャーへの移行は大きな一歩であり、多くの企業や開発者が同じように悪戦苦闘を強いられました。それより最近の、コアとなる Web ベースのアプリケーション・サーバーから SOA 導入への移行でも、同じような苦労を伴いました。これまで長い間、アプリケーション・サーバーを構成してきた多くのコンポーネントは、マイクロサービスに役立つと言っても、数ギガバイトのインストール・バイナリーにパッケージ化されていることに変わりはなかったためです。図 4 に、WebSphere Application Server および Java Enterprise Edition のコンポーネントを使用してデプロイされた、従来の Web アプリケーション・アーキテクチャーの例を示します。

図 4. 標準的な WebSphere Application Server アプリケーションのアーキテクチャー
WebSphere Application Server および Java Enterprise Edition のコンポーネントを使用してデプロイされた、従来の Web アプリケーション・アーキテクチャーの図
WebSphere Application Server および Java Enterprise Edition のコンポーネントを使用してデプロイされた、従来の Web アプリケーション・アーキテクチャーの図

マイクロサービスは、互いにやりとりするすべてのコンポーネントを極めて疎結合の状態で統合したものであり、マイクロサービスの発想全体がプラグ・アンド・プレイになっています。この点については「stronger ― より強力に」のセクションでさらに説明しますが、マイクロサービスをベースとしたシステムは基本的に、より大きな規模で「ショットガン法」を採用します。そうすることで、少数の大きなコンポーネントを対象とせずに、数多くの小さなコンポーネントを対象として保守およびセキュリティー確保を行うこととなり、単一障害点が取り除かれ、あらゆるところに障害点が分散されます。

障害に対処するよう構築するには、コンポーネントを小さく分割するしか方法はありません。障害に対処するモノリスを構築するとしたら、あらゆるエッジ・ケースの非効率性に取り組むのにあまりにも時間がかかってしまいます。単一のサービス・インスタンスで障害に対処する場合、コンシューマーからリクエストが送信されると、他のサービス・インスタンスが処理を引き継ぎます。

図 5 に、マイクロサービスを使用した実装の一例を示します。

図 5. ビデオ・ストリーミング・アプリケーションのルーティングの概念を示す例
スケーリングに必要なマイクロサービス・コンポーネントがデプロイされた、ビデオ・ストリーミング・アプリケーションの概念アーキテクチャーの図
スケーリングに必要なマイクロサービス・コンポーネントがデプロイされた、ビデオ・ストリーミング・アプリケーションの概念アーキテクチャーの図

図 5 の個々のボックスは、単独で保守され、単独でスケーリングされます。これらのボックスはその位置する場所、必要な情報の取得先を把握しています。すべてのマイクロサービス・アーキテクチャーに、この図に示されているすべてのコンポーネントが必要となるわけではありませんが、これらのコンポーネントが揃っていると役に立ちます。

図 4 と図 5 を比較すると、同様のアプリケーションをデプロイする方法の違いがわかるはずです。図 4 では、垂直スケーリングされるシステム上の単一プロセスに、あらゆるコンポーネントがデプロイされます。スループットを高める必要が出てくると、その都度サーバー・スタック全体が複製され、複製された各サーバーがそれぞれに専用のプロセス内で実行されます。図 4 の Web サービス・エンジンまたは EJB コンテナーでスループットを高める唯一の方法は、サーバー JVM 全体を、クラスター環境内の新しいインスタンスへとスケーリングすることです。ただしその場合、Web コンテナー、組み込み HTTP サーバー、メッセージング・エンジンなどのコンポーネントをスケーリングする必要があるかないかに関わらず、これらのコンポーネントがまた別に作成されることになります。

図 4 のタイプのスケーリングとは対照的に、図 5 のコンポーネントは独立してスケーリングが行われます。個々のコンポーネントと、そのスケーリング方法は「faster ― より迅速に」のセクションで説明することとして、ここでは各コンポーネントとサービスが分散されるという特質に注目します。図 4 のサンプル・アプリケーションで可用性を実現するには、高可用の Web アプリケーション・サーバーのフル・スタックが必要となりますが、図 5 のコンポーネントはそれとは異なり、本来分散されていて、焦点が絞られた単一の機能だけを (多くの場合、他のコンポーネントとは異なるテクノロジーを使用して) 提供します。この構造により、アプリケーション・アーキテクチャーをより迅速に進化させて、最新のテクノロジーならびに最新のリリースを他のコンポーネントとは関係なく組み込むことができます。

要するに、コンポーネントが小さければ小さいほど、開発、運用、保守、相互作用が容易になるというわけです。

faster ― より迅速に

クラウドに伴って、DevOps というバズワードも登場しました。DevOps のムーブメントによって、開発者は作成するコードをデリバリー・パイプラインに沿って管理し、継続的インテグレーションを行い、可視性を高められるようになります。DevOps の主要な原則は、図 6 に時計回りの方向で示されているように、観察 (Observe)、方向づけ (Orient)、決断 (Decide)、行動 (Act) です。

図 6. DevOps の原則
DevOps の主要な原則「観察 (Observe)、方向づけ (Orient)、決断 (Decide)、行動 (Act)」を示す図

より小さいコンポーネントをより迅速に提供できれば言うことはありません。モノリシックなアプリケーション・サーバー・インスタンスに、例えば 2 週間おきに更新を提供する手立てはありませんが、多数のサービスが利用する単一のサービスに対してであれば、同じ 2 週間という時間枠で確実に更新を提供することができます。コンポーネントのサイズを小さくすれば、新しいステージング環境を構築して、パイプラインを通じて本番環境にアイテムを提供する際のオーバーヘッドも減ります。

ただし、勘違いしないでください。モノリスでも継続的デリバリーや継続的インテグレーションを行うことはできます。実際にそうしているのを目にしたこともあります。しかしそれは、ビー玉ではなく大きな石でジャグリングするようなものです。大きな石を落した場合より、ビー玉を落とした場合の方が、態勢を立て直すのは遥かに簡単です。

DevOps に伴う開発サイクルは、マイクロサービスで大いに功を奏します。DevOps では、長期にわたる開発サイクルで完全な全体像を一度に構築するのではなく、短期の開発サイクルで継続的に機能を追加していくことを目指します。アジャイル開発と呼ばれる、このような開発手法が、DevOps を成功に導くための基本的なプラクティスです。反復開発または増分開発のどちらを選ぶかに関わらず、マイクロサービス、DevOps 文化、アジャイル・プランニングを組み合わせれば、過去のウォーターフォール型プロセスで最初のサイクルを計画するのにかかっていた時間で、インフラストラクチャー全体を迅速に構築することができます。

「より迅速に」のもう 1 つの側面は、実行に関連します。マイクロサービスは、プロセスをより速く進める必要がある場合に、より多くのリソースを投入するという考えに基づいています。これはまさに、管理者の夢です!それぞれのサービスが独立してスケーリングできるようにすべてのサービスを作成すると、コンポーネント間の相互作用に、単一のコンポーネント・インターフェースではなく、リソースのプールを利用できるようになります。

前の例に戻ると、図 5 にはサービス・レジストリー (Service registry) のサーバーとクライアントが示されています。これは、マイクロサービスをベースとしたアプリケーションに不可欠の機能です。この例では、エッジ・サービス (edge service) に映画サービス (Movie service) とレビュー・サービス (Review service) への参照が含まれています。これらのサービスがスケーリングする速度は負荷に応じて異なるため、もはやすべてのサービスを同じ規模で同じ方法で管理することはできません。

映画サービス (Movie service) がスケーリングすると、サービス・レジストリー (Service registry) は、新しく作成されたサービス・インスタンスを自動的に認識します。エッジ・サービス (edge service) はリクエストの処理を試みる際に、サービス・レジストリー (Service registry) を呼び出して、自身が依存するすべてのサービスに対するクライアントからの参照を取得します。映画サービス・クライアント (Movie service client) からの参照は、かなり最近作成された新しいインスタンスである可能性が高い一方、レビュー・サービス・クライアント (Review service client) からの参照は、前に使われた古いインスタンスが返される可能性もあります。このサービス・レジストリー (Service registry) 機能により、コンポーネント間の依存関係は疎結合の状態になっていながらも、必要に応じてコンポーネントを何回も複製して追加することができる、極めて高い信頼性が確保されるため、マイクロサービスはまさに「数あるサービスの 1 つ」としての役割を果たすことができるのです。

図 7 に、図 5 に示したビデオ・ストリーミング・アプリケーションに映画サービス (Movie service) のマイクロサービスをスケールアウトして追加したアーキテクチャー概念図を示します。

図 7. ビデオ・ストリーミング・アプリケーションのスケーリング概念の例
必要に応じてマイクロサービスが個別にスケーリングされる、ビデオ・ストリーミング・アプリケーションの概念アーキテクチャーを示す図
必要に応じてマイクロサービスが個別にスケーリングされる、ビデオ・ストリーミング・アプリケーションの概念アーキテクチャーを示す図

新しいインスタンスを自己認識するシステムでは、必要に応じてスケーリングが効率的に行われます。これは、スカイネット (映画『ターミネーター』シリーズに登場する架空のコンピューター) ではありません。マイクロサービス・アーキテクチャーをベースに作成されたアプリケーションを極めて強力にする仕組みです。

stronger ― より強力に

すべてのシステムが、長時間存続するように意図されているわけではありません。システムは必要に応じて作成され、その目的を果たさなくなると削除されます。前述のとおり、こうした仕組みによって、障害点をシステム全体に分散することで、単一障害点が取り除かれます。そして、利用できない状態または低パフォーマンスの状態にあるサービスやインスタンスを無効にするメカニズムが必要であることがわかります。

ペットではなく、家畜です

マイクロサービスでは、デプロイ済みシステムはペットではなく家畜として考えられます。

  • ペットには名前が付けられますが、家畜には番号が付けられます。
  • ペットはそれぞれに特徴がありますが、通常、家畜はどれも同じです。
  • ペットが病気になると、看病されて元気になりますが、家畜が病気になったら交換されるだけです。

— 出典: Gavin McCance 氏のプレゼンテーション「CERN Data Centre Evolution

この考え方からすると、サービスを作成するということは、1 つのサービスを多数作成することであると同時に、数あるサービスのうちの 1 つを作成することになります。そうなると、サービス・インスタンスの数を片手で数えることはなくなるとともに、長期間存続するインスタンスを管理して、状態の維持や、ストレージ、システムの変更などに気を遣うこともなくなります。誤解のないように言っておきますが、パフォーマンス・チューニングと構成が大きな関心事であることに変わりはありません。しかし、これらの関心事には、ステージングや本番の際ではなく開発サイクルのかなり初期の段階で対処することになります。この手法に従うと、多数のサービスが作成され、それぞれのサービスごとに多数のインスタンスが作成されます。

この仕組みの強さを支える柱をサービス作成の過程で検証するために、Netflix はカオス、正確には Chaos Monkey を用いるようになりました (図 8 を参照)。Chaos Monkey は、システムで制御されたカオスをアプリケーションの運用にもたらすために、Netflix が使用しているクラウド・アプリケーション・コンポーネントです。

図 8. Chaos Monkey
システムで制御されたカオスをアプリケーションの運用にもたらすために使用される、Chaos Monkey と名付けられたクラウド・アプリケーション・コンポーネントのイメージ
システムで制御されたカオスをアプリケーションの運用にもたらすために使用される、Chaos Monkey と名付けられたクラウド・アプリケーション・コンポーネントのイメージ

この Chaos Monkey の機能によって、インフラストラクチャー全体が調べられ、本番環境に不可欠なサービスやサービス・インスタンスが意図的に無効にされます。Netflix はなぜこのようなことを行うのでしょう?また、どのようにしてこれを実現することができ、どのようにしてその状態から回復できるのでしょう?

まず、なぜこのようなことを行うかですが、それは真っ先に障害を発生させる必要がある場所を簡単に突き止める手段となるからです。新しいサービスは処理速度が遅すぎませんか?サービスをもっと効率的にスケーリングする必要がありますか?内部サービスだけでなく外部サービス・プロバイダーもダウンしたとしたらどうなるのでしょう?マイクロサービス・アーキテクチャーでは、このようなことをすべて考慮しなければなりません。

次に、どのようにして回復するかですが、Netflix は前述のショットガン法のおかげで回復できるようになっています。発想は単純で、リクエストの 99.9999 パーセントを正常に完了できるだけの十分なサービス・インスタンスをプロビジョニングするというものです。失敗したリクエストは、再試行されます。サービス・インスタンスを無効にすると、その役目を別のローカル・インスタンスが引き継ぎます。サービス全体を無効にすると、システムが補うか、その特定のサービスを使用できる別のゾーンまたは別の地域にユーザーを再ルーティングします。他に有効な手段がなければ、ユーザーすなわちリクエストはタイムアウトを待たずに失敗します。

Netflix は Chaos Monkey の概念を拡張し、その機能を Simian Army としてリリースしました (図 9 を参照)。Simian Army に組み込まれている Chaos Monkeys、Janitor Monkeys、Conformity Monkeys、および Latency Monkeys は、サービス運用にレイテンシーやコンプライアンスの問題をはじめとする特定のカオスを引き起こす、クラウド・アプリケーション・コンポーネントです。

図 9. Simian Army
サービス運用にレイテンシーやコンプライアンスの問題をはじめとする特定のカオスを引き起こす、クラウド・アプリケーション・コンポーネントを表す絵

このように、Netflix (および、マイクロサービスを採用している他の企業) は、アプリケーションを機能させなくする問題がアプリケーションをより強力にするという考えに従っているのです。

まとめ

この記事で取り上げた、マイクロサービスの主要な利点は以下のとおりです。

  • サイズが小さいことから、開発者がより生産的に作業することができます。
  • それぞれのサービスを簡単に理解してテストすることができます。
  • あらゆる従属サービスの障害を適切に処理することができます。
  • 関連する障害の影響を軽減します。

謝辞および画像に関するクレジット

私が考えをまとめて方向づけるために使用したプレゼンテーションの作者、Jonathan Bond 氏に感謝いたします。このプレゼンテーションから、いくつかの画像 (図 1、5、6、および 7) も引用させてもらいました。

外部からの画像に関するクレジット: 図 3図 4図 8図 9


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Cloud computing, Web development
ArticleID=1014642
ArticleTitle=マイクロサービス入門
publish-date=01102018