December 2015

Volume 30 Number 13

Microsoft Azure - Azure Service Fabric とマイクロサービス アーキテクチャ

Cesar de la TorreKunal Deep Deep | December 2015

「マイクロサービス」という業界用語を耳にする機会が最近多くなりました。このテーマを取り上げたプレゼンテーションやカンファレンス セッションが多数行われていますが、多くの開発者は混乱しています。よく聞かれるのは、「サービス指向アーキテクチャ (SOA) やドメイン駆動設計 (DDD) によるアプローチとどこが違うの」という質問です。

確かに、マイクロサービスによるアプローチで使用されている多くのテクニックは、SOA や DDD で開発者が経験したことから生み出されたものです。マイクロサービスは、「適切に行われた SOA」と考えてもかまいません。つまり、自立型サービス、境界コンテキスト パターン、イベント駆動型のような原則とパターンを備えた SOA です。こうした原則やパターンは、すべて SOA と DDD がルーツです。

ここでは、マイクロサービスの理論と実装の両面を取り上げます。まず、マイクロサービスについて簡単に紹介します。次に、その実用面と、Azure Service Fabric を使用してマイクロサービスをビルドおよびデプロイ (配置) する方法を示します。最後に、Azure Service Fabric がマイクロサービスのビルドに非常に適している理由を説明します。

名前から推測できるように、マイクロサービス アーキテクチャとは、サーバー アプリケーションを小さなサービスの集合体としてビルドするアプローチです。各サービスは独自のプロセスで実行され、HTTP や WebSockets などのプロトコルを使って相互に通信します。各マイクロサービスは、サービスごとに特定の境界コンテキスト内にエンドツーエンドのドメイン機能やビジネス機能を実装します。また、マイクロサービスは、それぞれ自立して開発し、自動メカニズムによって個別にデプロイする必要があります。最後に、各サービスは関連するドメイン データ モデルとドメイン ロジックを持ち、マイクロサービスごとに異なるデータ ストレージ テクノロジ (SQL、No-SQL) や異なるプログラミング言語を使用できるようにします。

マイクロサービスの例には、プロトコル ゲートウェイ、ユーザー プロファイル、ショッピング カート、在庫処理、購入サブシステム、支払い処理、キューとキャッシュなどがあります。

マイクロサービスを使用する理由をひと言でいえば、機敏性です。長期的には、多数のサービスを基盤とするアプリケーションを設計できます。さらに、各サービスは個別にデプロイ可能なので、リリースをきめ細かく計画できます。その結果、保守性に優れた大規模で複雑な拡張性の高いシステムを実現できます。

また、個別にスケールアウトできることもマイクロサービスのメリットです。巨大でモノリシックなアプリケーション ブロックを一度にスケールアウトするのではなく、特定のマイクロサービスをスケールアウトできます。その結果、需要に応えるために多くの処理能力やネットワーク帯域幅を必要とする機能領域だけをスケールアウトでき、本来スケールアウトする必要のない機能領域までスケールアウトすることはありません。

きめの細かいマイクロサービス アプリケーションを設計すると、継続的インテグレーションや継続的開発プラクティスが実現され、アプリケーションに新しい機能を迅速に提供できるようなります。また、アプリケーションを細分化することで、マイクロサービスの実行とテストを個別に行い、マイクロサービス間の厳密なコントラクトを維持したまま、サービスを個別に進化させることができます。コントラクトやインターフェイスを損なわない限り、任意のマイクロサービスの実装を内部で変更したり、新しい機能を追加しても、そのマイクロサービスに依存する他のマイクロサービスに支障が出ることはありません。

図 1 に示すように、マイクロサービス アプローチによってビルドした大規模で複雑なスケーラビリティが高いアプリケーションは、その特定の小さな部分だけを変更できるため、迅速な変更やすばやい反復操作を効率的に行えます。

マイクロサービス アプローチと従来のサーバー アプリケーション アプローチの比較
図 1 マイクロサービス アプローチと従来のサーバー アプリケーション アプローチの比較

マイクロサービス単位のデータ管理

このアプローチの重要な原則は、各マイクロサービスには自立したライフサイクルに基づくドメイン データとロジックが必要で、マイクロサービス単位に個別にデプロイできなければならないことです。これは、アプリケーション全体のロジックやデータ管理に求められることと、なんら違いはありません。

このアプローチでは、サブシステムとマイクロサービスとの間で、ドメインの概念モデルが異なるものになります。顧客関係管理 (CRM) アプリケーション、取引購買サブシステム、顧客サポート サブシステムから成るエンタープライズ アプリケーションがあるとします。ここで、各アプリケーションやサブシステムは、それぞれ特有の顧客エンティティ属性やデータを呼び出し、異なる境界コンテキストを利用します。

この原則は、各境界コンテキスト (サブシステム/サービスに相当するパターン) にドメイン モデル (データとロジック) が必要な DDD に似ています。つまり、各 DDD 境界コンテキストが、それぞれ別のマイクロサービスに相当します。

一方、多くのアプリケーションで使用される従来型の (モノリシックな) アプローチの場合、アプリケーション全体とその内部のすべてのサブシステムは、1 つの一元管理されるデータベース (通常は正規化された SQL データベース) を必要とします (図 2 参照)。このアプローチは、最初は単純に思え、さまざまなサブシステムでエンティティを再利用してすべての一貫性を保てるように思えます。しかし、実際は、多くの異なるサブシステムにサービスを提供し、ほとんどの場合に必要とされない属性や列を含んだ大きなテーブルを用意することになります。これは、短い散歩にも、日帰りドライブにも、地理の勉強にも、同じ縮尺の地図を利用するようなものです。

データ管理の比較: マイクロサービスとモノリシック
図 2 データ管理の比較: マイクロサービスとモノリシック

マイクロサービスをステートレスにするかステートフルにするか

前述のように、各マイクロサービスはそれぞれ独自のドメイン モデルを所持する必要があります。ステートレス マイクロ サービスの場合、データベースはサービス外部に用意することになります。このデータベースは、SQL Server などのリレーショナル データベースでも、MongoDB、Azure Document DB などの NoSQL データベースでもかまいません。サービス自体をステートフルにして、データを同じマイクロサービス内に常駐させることもできます。このデータは、同じサーバー内に存在できるだけでなく、マイクロサービスの同じプロセス内であれば、メモリ内に存在することも、ハード ドライブに保存することも、他のノードにレプリケートすることもできます。

ステートレスはまったく問題のないアプローチで、従来から使い慣れているパターンに似ているため、ステートフルなマイクロサービスを実装するよりも簡単です。しかし、ステートレスなマイクロサービスでは、プロセスとデータ ソースの間で遅延が発生します。ただし、動的な部分も多数存在するため、パフォーマンスを向上するにはキャッシュやキューを追加することになります。その結果、過度に多くの層から構成される複雑なアーキテクチャになる可能性があります。

一方、ステートフルなマイクロサービスはドメイン ロジックとデータの間に遅延が生じないため、高度なシナリオに優れています。負荷の高いデータ処理、ゲームのバックエンド、サービスとしてのデータベースなど、あまり遅延が許されないシナリオでは、ローカルな状態で高速にアクセスできるステートフル サービスのメリットを生かすことができます。

デメリットは、ステートフル サービスではスケールアウトが複雑になることです。通常外部データベース境界内に実装する機能は、ステートフル マイクロサービス レプリカにまたがるレプリケーションや、データのパーティション分割などの機能として対処する必要があります。しかし、このようなスケールアウトの問題に大きな支援を提供するのが Service Fabric です。Service Fabric によって、ステートフル マイクロサービスの開発とライフサイクルが簡略化されます。

Azure Service Fabric のメリット

マイクロサービス アプローチのメリットにはすべて、デメリットが伴います。分散コンピューティングと複雑なマイクロサービスのデプロイは、自分自身で行うと管理が難しくなる可能性があります。Service Fabric は、マイクロサービスを効果的かつ効率的に作成、デプロイ、実行、および管理するために必要な機能を提供します。

Service Fabric とは、スケーラビリティが非常に高く、信頼性に優れ、簡単に管理できるクラウド向けアプリケーションを構築するために使用される分散システム プラットフォームです。Service Fabric は、クラウド アプリケーションの開発と管理における大きな課題に対処します。Service Fabric を使用することで、開発者と管理者は、複雑なインフラストラクチャの問題を解決する必要がなくなり、ミッションクリティカルで要件の厳しいワークロードの実装に専念できます。実装されるワークロードは、スケーラビリティと信頼性が高く、管理しやすいワークロードになることがわかっています。Service Fabric は、このようなエンタープライズ クラスの Tier-1 クラウド スケール サービスをビルドおよび管理するためのマイクロソフトの次世代ミドルウェア プラットフォームを表しています。

Service Fabric は、汎用のデプロイ環境で、任意の言語 (Microsoft .NET Framework、Node.js、Java、C++) に基づく任意の実行可能ファイルまたは MongoDB などのデータベース ランタイムをデプロイできます。

したがって、Azure Service Fabric の用途は、明らかにマイクロサービス指向アプリケーションには限定されません。Service Fabric を従来型のアプリケーション (Web アプリケーションやサービス) のホストやデプロイに使用して、スケーラビリティ、負荷分散、高速なデプロイにまつわるさまざまなメリットを得ることもできます。ただし、Azure Service Fabric は、ゼロから構築され、ハイパースケールでマイクロサービス ベースのシステムのために特別に設計された新しいプラットフォームです (図 3 参照)。

Microsoft Azure Service Fabric
図 3 Microsoft Azure Service Fabric

以下に、Service Fabric のメリットをいくつか示します。

  • Azure、オンプレミス、任意のクラウドで実行可能: Service Fabric の非常に重要な特性は、Azure だけでなく、オンプレミス、独自のベアメタル サーバー、仮想マシン (VM)、および他のサードパーティによってホストされるクラウドでも実行できることです。特定のクラウドに縛り付けられることはありません。Service Fabric クラスターを Amazon Web Services (AWS) で実行することもできます。
  • Windows と Linux のサポート: 現在 (2015 年後半)、Service Fabric のサポート対象は Windows ですが、今後、Linux とコンテナー (Windows イメージと Docker イメージ) もサポート予定です。
  • 十分検証済み: Service Fabric は、マイクロソフトによって数年間使用されており、数多くのクラウド製品で利用されています。

Service Fabric は、マイクロソフト内で大規模サービスをビルドする必要性から生まれました。SQL Server などの製品を利用して、それらをクラウドで利用可能なサービス (Azure SQL Database) としてビルドし、同時に機敏性、信頼性、拡張性、コスト効率を実現するには、それらの需要すべてを効果的に満たすことのできる分散テクノロジが必要でした。このような複雑なシナリオを解決するコア テクノロジをビルドする過程で、同様の効果が得られる製品は SQL Server だけではないことが明らかになりました。Skype for Business などの製品も、マイクロサービスベースのアプリケーションにする過程で似たような問題を解決する必要があります。Service Fabric は、このような課題から進化したアプリケーション プラットフォームです。マイクロソフトでは、大規模環境で実行するために必要な多種多様なアーキテクチャや要件を持つ、数多くの大規模サービスにこれを使用しています。InTune、DocumentDB、および Cortana と Skype for Business のバックエンドはすべて、Service Fabric 上で実行されるサービスです。

マイクロソフトは、ミッション クリティカルなシステムをサポートしてきたる経験から、スケーラビリティの高いアプリケーションに必要な本質的なリソースやニーズを理解して、このプラットフォームの設計を可能にしています。これにより、可用性が高く、永続性のあるサービスのハイパースケールでの提供に不可欠な、自動更新、自己復旧動作が可能になります。マイクロソフトは、この百戦錬磨のテクノロジをだれでも利用できるようにしました。

Azure Service Fabric のプログラミング モデル

Service Fabric には、Reliable Services API と Reliable Actors API という、サービスをビルドするための 2 つの高水準フレームワークが用意されています。どちらの API も、同じ Service Fabric コア上にビルドされていますが、同時実行性、パーティション分割、および通信の点で、簡潔さと保守性との間でさまざまなトレードオフが行われています (図 4 参照)。両方のモデルの動作を理解すると、サービスに適したフレームワークを選択できます。多くのアプリケーション シナリオでは、特定のマイクロサービスに対してアクターを使用し、さまざまなアクターによって生成されたデータの集約に信頼性の高いサービスを使用するというハイブリッド アプローチを採用できます。つまり、よくあるシナリオの多くで、信頼性の高い 1 つのサービスから複数のアクター サービスを編成できます。

図 4 Service Fabric プログラミング モデルの比較

Reliable Actor API Reliable Services API
シナリオに状態とロジックの多数の小さな独立した単位/オブジェクト (ライブ IoT オブジェクトや、ゲームのバックエンド シナリオなど) が含まれる エンティティの複数の種類とコンポーネント間でロジックとクエリを管理する必要がある
処理するシングルスレッド オブジェクトは膨大だが、同時に、拡張可能かつ一貫性を維持できる 信頼性の高いコレクション (.NET Reliable Dictionary と Reliable Queue など) を使用して状態/エンティティを格納、管理する
フレームワークによって同時実行性と状態の粒度が管理される 状態の粒度と同時実効性を制御する必要がある
Service Fabric によって通信の実装が管理される 通信プロトコル (Web API、WebSocket、Windows Communication Foundation など) を決定、管理、実装する必要がある
Service Fabric によって管理されるため、ステートフル アクター サービスのパーティション分割方式を意識する必要がない ステートフル サービスのパーティション分割方式を制御する必要がある

Azure Service Fabric によるステートレス マイクロサービスのビルド

Azure Service Fabric のマイクロサービスは、NET Framework、Node.js、Java、C++ など、言語が何であろうと、作成するサーバーでほとんど任意のプロセスにすることができます。.現在、Service Fabric API で利用可能なのは、.NET と C++ のライブラリだけです。したがって、低レベルの実装では、.NET Framework または C++ でマイクロサービスを実装する必要があります。

前述のとおり、ステートレス マイクロサービスは、プロセスが存在するサービス (フロントエンド サービスまたはビジネス ロジック サービスなど) です。しかし、ステートレスの文字どおり、永続化する状態 (ステート) がサービス内に存在しないか、プロセスが終了して、同期、レプリケーション、永続性、または高可用性が不要な場合、存在する状態が失われます。Azure SQL Database、Azure Storage、Azure DocumentDB、またはその他のサードパーティ製ストレージ エンジン (リレーショナルまたは NoSQL) などの外部ストレージに存在する状態については、関連する外部状態として所持できます。したがって、Cloud Services、worker ロール、または Azure Web App で実行している ASP.NET Web API サービスなどの既存のサービスは、簡単に Service Fabric ステートレス サービスに移行できます。

開発環境をセットアップするには、Service Fabric SDK を用意する必要があります。この SDK により、ローカル開発クラスターを実行できるようになります。このクラスターはエミュレーターではありませんが、Azure と同じ機能を実行します。また、Visual Studio 2015 ツールを統合すると、開発とデバッグがさらに簡単になります。

ローカル コンピューターにサービスをデプロイしてデバッグする前に、ノードのクラスターを作成する必要があります。これを行うには、ドキュメント ページ「開発環境を準備する」(bit.ly/1Mfi0LB) の「ローカル クラスターをインストールして開始します」セクションで説明されている、DevClusterSetup.ps1 という Windows PowerShell スクリプトを実行します。セットアップ プロセスの完全なチュートリアルについては、このページを参照してください。

ステートレス サービス基本クラス: ステートレス Service Fabric サービス クラスはすべて、Microsoft.ServiceFabric.Services.StatelessService クラスから派生する必要があります。このクラスは、API のメソッドや Service Fabric クラスターと実行環境に関連するコンテキストを提供し、サービスのライフサイクルにフックします。

サービスがステートフルとステートレスのどちらでも、Reliable Services は、すばやくコードをプラグインして開始できる単純なライフサイクルを提供します。Service Fabric サービスを構成して実行するために実装する必要のあるメソッドは、わずか 1 つか 2 つ (通常は RunAsync と CreateServiceReplicaListeners) です。これらについては、通信プロトコルにを取り上げるときに説明します。

図 5 に示す RunAsync に注目してください。このようにすると、サービスはバックグラウンドで「作業」できます。指定しているキャンセル トークンは、作業を停止するタイミングのシグナルです。

図 5 Azure Service Fabric のステートレス サービスの基本構造

using Microsoft.ServiceFabric.Services;
namespace MyApp.MyStatelessService
{ 
  public class MyStatelessService : StatelessService
  {
    //... Service implementation
    protected override async Task RunAsync(CancellationToken cancellationToken)
    {   
      int iterations = 0;
      while (!cancellationToken.IsCancellationRequested)
      {
        ServiceEventSource.Current.ServiceMessage(this, "Working-{0}",
          iterations++);
        // Place to write your own background logic.
        // Example: Logic doing any polling task.
        // Logic here would be similar to what you usually implement in
        // Azure Worker Roles, Azure WebJobs or a traditional Windows Service.
         await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
      }
      } 
    }
}

Azure Service Fabric Reliable Services の通信プロトコル: Azure Service Fabric Reliable Services は、プラグ可能な通信モデルを提供します。HTTP と ASP.NET Web API、WebSockets、Windows Communication Foundation、カスタム TCP プロトコルなど、好みのトランスポートを使用できます。

選択した通信プロトコル用の独自のコードをサービスに実装できるほか、Service Fabric に用意されている ServiceCommunicationListener/ServiceProxy などの通信スタックを使用できます。ServiceCommunicationListener/ServiceProxy は、Service Fabric で Reliable Services Framework によって提供される既定の通信スタックです。また、Service Fabric にプラグ可能な追加の通信スタックを含む個別の NuGet パッケージもあります。

Service Fabric マイクロサービスでの ASP.NET Web API の使用: 前述のとおり、Service Fabric では開発者がサービスの通信方法を決定できますが、.NET Framework で HTTP サービスを作成する最も一般的な方法の 1 つは、ASP.NET Web API を使用することです。

Service Fabric の Web API は、使い慣れた ASP.NET Web API と同じです。コントローラー (HttpRoutes) を使用するほか、MapHttpRoute や Http ルートにマップするメソッド属性を使用して同じように REST サービスをビルドできます。Service Fabric 使用する場合の違いは、Web API アプリケーションのホスト方法です。まず考慮するのは、Azure Service Fabric では IIS を使用できないことです。Azure Service Fabric では、クラスター全体にレプリケートされるプレーンなプロセスのみを使用するため、コード内で HTTP リスナーを自己ホストする必要があります。これを Web API サービスに対して行う方法には、次の 2 つがあります。

  • ASP.NET 5 Web API (コードネーム「Project K」) を使用して、Service Fabric マイクロサービス プロセス内で HTTP リスナーを自己ホストする。
  • OWIN/Katana と ASP.NET 4.x Web API を使用して、Service Fabric マイクロサービス プロセス内で HTTP リスナーを自己ホストする。

マイクロサービスをビルドする場合は、Azure Service Fabric を基盤に ASP.NET 5 を実行するのが最も適しています。前述のように、Service Fabric では各ノード/VM にサービスをいくつでもデプロイできるため、クラスターあたりのマイクロサービスの密度を高くすることができます。また、将来 Service Fabric で (ASP.NET 5 の下で) .NET Core 5 と CoreCLR のサポートが提供されるようになると、さらに密度を上げることができます。.NET Core 5 は、完全版の .NET 4.x Framework に比べると、メモリ占有領域が非常に少ない軽量なフレームワークなので、非常に高密度のマイクロサービスを実現する「最善の選択肢」になるでしょう。

"MVC 型" Web アプリケーションと Service Fabric マイクロサービスの使用: ASP.NET MVC は従来型の Web サイトで非常によく使われているフレームワークですが、「古い」MVC フレームワーク (MVC 5 以前) を Service Fabric と併用することはできません。それは、Service Fabric では HTTP リスナーを自己ホストする必要があり、OWIN/Katana がASP.NET 4.x MVC ではサポートされていないためです (ASP.NET 4.x Web API のみでサポート)。したがって、Service Fabric で "MVC 型" Web アプリケーションを実装するための選択肢は以下のとおりです。

  • ASP.NET 5 で MVC 6 を使用して Service Fabric マイクロサービス プロセス内で HTTP リスナーを自己ホストします。ASP.NET 5 では、Web API と MVC が統合されて、コントローラーが共通で IIS への依存関係のない 1 つのフレームワークになったため、MVC がサポートされます。これは、ASP.NET 5 が RTM 版になったらお勧めの選択肢です。
  • ASP.NET 4.x Web API と OWIN/Katana を一緒に使用して Service Fabric マイクロサービス プロセス内で HTTP リスナーを自己ホストし、Web API コントローラーを使用して MVC コントローラーをシミュレーションします。通常の Web API コンテンツ (JSON/XML) ではなく HTML/JavaScript 出力を使用します。ドキュメント ページ bit.ly/1UMdKIf に、この手法の実行方法が説明されています。

ASP.NET 4.x Web API と OWIN/Katana による自己ホストの実装

このアプローチでの Web API アプリケーションに対する取り組みはこれまでと変わりません。過去に作成した Web API アプリケーションと何の違いもなく、アプリケーションのほとんどを単純に移動できます。これまで IIS でアプリケーションをホストしていた場合、ホスト方法は若干変わる可能性はあります。

サービス クラスの CreateServiceReplicaListeners メソッド: ここで、サービスで使用する通信スタックを定義します。Web API などの通信スタックは、サービスのリッスン エンドポイント、および表示されるそれらのメッセージがサービス コードの残りの部分とやり取りする方法を定義します。

図 5 で触れたサービス クラスに戻って、ここで、CreateServiceReplicaListeners という新しいメソッドを追加します。これは、使用する通信スタックを少なくとも 1 つ指定します。今回の場合、その通信スタックは、Web API で使用される OwinCommunicationListener です (図 6 参照)。

図 6 ステートレス サービス クラスへの CreateServiceReplicaListeners メソッドの追加

using Microsoft.ServiceFabric.Services;
namespace MyApp.MyStatelessService
{ 
  public class MyStatelessService : StatelessService
  {
    //... Service implementation.
    protected override async Task RunAsync(CancellationToken cancellationToken)
    {            
      // Place to write your own background logic here.
      // ...         
    }
    protected override IEnumerable<ServiceReplicaListener>
      CreateServiceReplicaListeners()
      {
        return new List<ServiceReplicaListener>()
        {
          new ServiceReplicaListener(parameters =>
            new OwinCommunicationListener(
            "api", new Startup()))
        };
      } 
    }
}

サービスに複数の通信リスナーを追加できることは重要なので、強調しておきます。

OwinCommunicationListener クラスは、すべてのマイクロサービスで再利用できるスケルトン コードです。同じように、他のプロトコル (WCF、WebSockets など) をプラグインできます。

Web API マイクロサービスを作成している場合、Web API サービスを実装するときに使用するのと変わらない一般的なコードを使用してコントローラーを実装することになります。たとえば、以下のようなコードです。

// Typical Web API Service class implementation
public class CustomerController : ApiController
{ 
  //// Example - GET /customers/MSFT
  [HttpGet]
  [Route("customers/{customerKey}", Name = "GetCustomer")]
  public async Task<IHttpActionResult> GetCustomer(string customerKey)
  {
    // ... Stateless method implementation.       
  }
}

今回は、Azure Service Fabric とマイクロサービスについて隅々まで概観することが目的なので、Service Fabric マイクロサービスに OWIN を実装する手順については取り上げません。ダウンロードして分析可能な単純な例が GitHub に公開されています (Web API と Service Fabric による HelloWorld サンプル (ASP.NET 4.x)、bit.ly/1OW5Bmj、英語)。

ASP.NET 5 Web API による自己ホストの実装

マイクロサービスをビルドする場合は、Azure Service Fabric を基盤に ASP.NET 5 を実行するのが最も適しています。Service Fabric では各ノード/VM にサービスをいくつでもデプロイできるため、クラスターあたりのマイクロサービスの密度を高くすることができます。そのうえ、ASP.NET 5 には、次のような魅力的な機能が用意されています。

  • 柔軟なホスティング: ASP.NET 5 アプリケーションは、IIS または独自のプロセスでホストできます。Azure Service Fabric では、独自のプロセスでホストするのが基本です。
  • Web API、MVC、Web ページ: これらがすべて統合され、概念の数が簡略化されます。
  • 完全なサイドバイサイド サポート: コンピューターにインストールされている別の .NET Framework を使用するアプリケーションに影響することなく、ASP.NET 5 アプリケーションを同じコンピューターにインストールできます。これは、IT 管理にとって非常に役立つ機能です。
  • クロス プラットフォーム サポート: ASP.NET 5 は、Windows、Mac OS、および Linux で実行でき、サポートされます。
  • クラウド向け: 診断、セッション状態、キャッシュ、構成などの機能が、ローカルとクラウド (Azure など) で変わらず機能するように設計されています。

今後の展望としては、Service Fabric で .NET Core 5 と CoreCLR がサポートされると、高密度機能がさらに向上すると考えられます。

.NET Core と CoreCLR のサポートは Service Fabric で準備中ですが、サポートがオンラインに実装されたときのメリットは明白です。.NET Core 5 の上で ASP.NET 5 を実行すると、従来の .NET 4.x と比べて非常にメモリ占有領域の少ない軽量な .NET Framework と CoreCLR ランタイムが提供されます。この組み合わせにより、驚くべき高密度のマイクロサービスが実現します (図 7 の "Microservice B" パネル参照)。

CLR 上で実行される ASP.NET 5 と Service Fabric コンテキスト内の CoreCLR の比較
図 7 CLR 上で実行される ASP.NET 5 と Service Fabric コンテキスト内の CoreCLR の比較

.NET Core 5 と CoreCLR サポートは将来のオプションですが、Service Fabric で .NET 4.x を基盤とする ASP.NET 5 サービスを開発することで、今からこのサポートに備えることができます。このようにすると、今後の CoreCLR への移行が簡単になります。

ハイパースケール マイクロサービスの運用とデプロイ

Service Fabric によって提供される運用とデプロイの管理が、本番用ハイパースケール マイクロサービスをビルドして実行することをお勧めする理由の 1 つです。開発者はマイクロサービスの開発に専念し、複雑な内部のプラミングはすべて Service Fabric に任せることができます。

インフラストラクチャ コストの削減を考えている場合には、マイクロサービスが高密度であることが大きく役立ちます。Service Fabric クラスターは、クラスターのノードと呼ばれる多数の VM/サーバー (および将来的にはコンテナー) のプールで構成されます。各ノードで、Service Fabric は自動的にいくつかのサービスをデプロイします。そのため、各サーバー/VM の処理能力に応じて、クラスター全体にわたって非常に高密度なマイクロサービスを実現できます。

Azure Service Fabric では、各コンピューターまたは VM で何百ものサービス インスタンスを実行できます。これにより、総保有コスト (TCO) を大幅に削減できます。同じ量のサービスを実行する場合、必要なハードウェアは少なくなります。したがって、サービスごとに VM が 1 つに限定されている Azure Cloud Services と Azure Service Fabric を比べると、高密度が大きな差別要因になります。マイクロサービスを Web ロールや worker ロールとしてデプロイすると、おそらく 1 つのマイクロサービスにリソースを過度に割り当てることになり、デプロイ時や管理時に処理が低速になります。たとえば、図 8 では、Azure Web ロールまたは worker ロール形式のサービスのインスタンス 1 つにつき 1 つの VM があります (色はサービスの種類を表しており、各図形や四角形は異なる VM とサービス インスタンスを表しています)。高密度のマイクロサービスを求めている場合、小さい VM を使用しない限り、このアプローチは役立ちません。小さい VM を使用したとしても、やはり限界があり、どのようにデプロイしたとしても、Azure Service Fabric と比べて同じレベルの高密度を実現することはできません。

サービス密度の比較 - Azure Cloud Services と Service Fabric
図 8 サービス密度の比較 - Azure Cloud Services と Service Fabric

対照的に、Service Fabric では、各ノードに任意の数のマイクロサービスをデプロイできるため、サービスの密度ははるかに効率的で、コストは低くなります。1 つのクラスターあたり何十、何百、何千もの VM/サーバーをホストでき、各ノード/VM は、何十、何百ものマイクロサービス インスタンスやレプリカから構成できます。また、各マイクロサービスは単なるプロセスなので、Azure Cloud Services と同様、サービス単位に新しい VM を作成するよりも、デプロイとスケーリングがはるかに高速です。

Azure クラウドでのクラスターの作成: マイクロサービスをデプロイする前に、Azure またはオンプレミス サーバーでノードのクラスターを作成しておく必要があります。(運用環境やステージング環境のように) Azure クラウドでクラスターを作成する場合、Azure ポータルまたは Azure リソース マネージャーを使用して直接作業できます。図 9 は、Azure サブスクリプションで、Azure ポータルを使用して作成した Service Fabric クラスターを示しています。内部的には、クラスター作成プロセスは、Azure ARM と Azure リソース グループに基づいています。今回の場合、Azure リソース グループ内にも配置される 5 つのノード/VM で構成されるクラスターを作成しました。

Azure ポータルでの Service Fabric クラスター
図 9 Azure ポータルでの Service Fabric クラスター

クラスターへのアプリケーション/サービスのデプロイ: ノード/VM のクラスターが稼働したら、サービスをデプロイできます。運用クラスターにデプロイするときには、通常、Windows PowerShell スクリプトを使用して、アプリケーション/サービスを Azure のクラスターにデプロイします。ただし、ステージング/テスト環境の場合は、Visual Studio から直接デプロイすることもできます。

Visual Studio 2015 を使用して、開発 PC 上のローカル クラスターにデプロイする場合には、通常、Service Fabric アプリケーション プロジェクトを右クリックし、[配置] をクリックすることで、Visual Studio から直接デプロイします。Windows PowerShell を使用して、ノート PC の開発クラスターにデプロイすることもできます。これは、Azure クラウド ベースのクラスターと同様、同じ Service Fabric 機能が開発クラスターで実行されるためです。

毎日の運用やデプロイの管理が容易になることは、サービスを長期間スムーズに運用するために不可欠です。Service Fabric には、マイクロサービスベースのアプローチを念頭に、アプリケーション ライフサイクル管理機能が組み込まれています。Service Fabric で使用できる運用機能と管理機能には、高速デプロイ、ダウンタイムなしのアプリケーション アップグレード、サービスの正常性監視、およびクラスターのスケールアップ/スケールダウンがあります。ダウンタイムなしのアップグレードを可能にしているのは、Service Fabric のアップグレード テクノロジによって提供される、組み込みのローリング アップグレードと自動正常性チェックです。これらが連携して、アップグレードの変更によりアプリケーションが不安定になる場合はそれを検出してロールバックが行われます。Service Fabric クラスターとアプリケーションの管理機能は、Windows Powershell コマンドで実行でき、CLI とスクリプトのすべての能力を利用できます。また、使いやすいよう Visual Studio などのビジュアル ツールもサポートされています。

ローリング アップグレードは段階的に実行されます。各段階で、クラスターを構成するノードのサブセット (アップグレード ドメイン) にアップグレードが適用されます。そのため、アプリケーションは、アップグレード中も常に利用可能です。厳密なバージョン管理とサイドバイサイド サポートも提供されるため、同じマイクロサービスの v1 バージョンと v2 バージョンをデプロイすると、クライアントの要求に応じて、Service Fabric はいずれかのマイクロサービスにリダイレクトします。詳細については、bit.ly/1kSupz8 のドキュメントを参照してください。

PC 内のローカル開発クラスター内でサービスをデバッグする場合、デバッグ開始前からサービスのプロセスが既に運用されている場合でも、Visual Studio を使用するとデバッグが簡単になります。Visual Studio がプロジェクトに関連するすべてのマイクロサービス プロセスに自動的にアタッチされ、簡単にデバッグを開始して、Service Fabric マイクロサービス コードで標準ブレークポイントを使用できます。ブレークポイントをコードに設定し、F5 キーを押すだけです。Visual Studio をアタッチする必要のあるプロセスを探す必要はありません。

Service Fabric Explorer: 図 10 に示す Service Fabric Explorer は、クラスターによって提供される Web ベース ツールで、デプロイされたアプリケーション状態の視覚化、個別のノード コンテンツの調査など、さまざまな管理作業が可能です。Explorer ツールは、Service Fabric REST API をサポートし、http://<クラスターのエンドポイント>:19007/Explorer でアクセスできる同じ HTTP ゲートウェイ サービスから提供されます。ローカル クラスターの場合、URL は http://localhost:19007/Explorer になります。

Service Fabric Explorer
図 10 Service Fabric Explorer

Service Fabric Explorer の詳細については、ドキュメンテーション ページ「Service Fabric Explorer を使用したクラスターの視覚化」(bit.ly/1MUNyad) を参照してください。

Service Fabric プラットフォームでは、複雑な正常性システムやアップグレード可能なシステムの実装ではなく、アプリケーション開発に専念できるようなさまざまな機能を利用できます。たとえば、以下のような機能があります。

ステートレス サービスのスケールアウト: Service Fabric オーケストレーション エンジンは、新しいノードがクラスターに追加されるたびに、Web アプリケーションを多くのコンピューターに自動的にスケーリングします。ステートレス サービスのインスタンスを作成する際に、作成するインスタンス数を指定できます。Service Fabric は、その数に応じて、1 つのノードにインスタンスが 1 つだけ作成されるように、指定された数のインスタンスをクラスターのノードに配置します。また、インスタンス数に "-1" を指定すると、すべてのノードに必ず 1 つのインスタンスを作成するように Service Fabric に指示できます。これにより、ノードを追加してクラスターをスケールアウトするときに、ステートレス サービスのインスタンスが必ず新しいノードに作成されるようになります。

自動リソース分散: Service Fabric には、(VM のコンピューティングのように) クラスター内で利用可能なすべてのリソースを把握するサービス リソース分散 (サービス オーケストレーション) が備えられています。定義済みのポリシーと制約に基づいて自動的にマイクロサービスを移動することで、作成したサービスを VM 全体に配置する方法が最適化されます (図 11 参照)。この機能は、コストとパフォーマンスの最適化に重点を置いています。

ノード間のサービス分散と自動リソース分散を表したクラスター
図 11 ノード間のサービス分散と自動リソース分散を表したクラスター

組み込みのフェールオーバーとレプリケーション: データセンターまたはパブリック クラウドのコンピューターには、予期しないハードウェア障害が発生しがちです。そのようなシナリオを防ぐために、Service Fabric には組み込みのフェールオーバーとレプリケーション機能が用意されています。これにより、ハードウェアに障害が発生しても、サービスの可用性に影響しません。これが可能なのは、Service Fabric は、コンピューターと障害ドメインにまたがって各サービスの複数のインスタンスを運用、管理できるためです。

配置の制約: フロントエンド マイクロサービスを中間層マイクロサービスと同じコンピューター/ノードに配置しない、特定の種類のマイクロサービスを同じノードに配置しないなど、配置に関する指示をクラスターに行うことができます。こうした指示により、既知の競合を最小限に抑え、特定のマイクロサービスがリソースに優先的にアクセスできるようにします。

要求の負荷分散: 要求の負荷分散は、Service Fabric ではなく、Azure ロード バランサーなど、Service Fabric 外部のプラットフォームで処理されます。自動リソース分散と混同しないようにしてください。

正常性: システムを監視して診断できます。アプリケーションのアップグレード中に安全性を確認するために使用して、アップグレードによって不安定になる場合はアップグレードをロールバックできるようにします。詳細については、ドキュメンテーション ページ「Service Fabric の正常性モニタリングの概要」(bit.ly/1jSvmHB) を参照してください。

Azure Service Fabric におけるステートフル マイクロサービス

ステートフル サービスのサポートは、Azure Service Fabric の魅力的かつ重要な要素です。ステートフル サービス自体の説明も、複雑で広範囲にわたるため、本稿で扱う範囲を超えますが、ここでステートフル サービスの考え方を簡単に説明しておきます。今後の MSDN マガジンで、Service Fabric のこの分野について取り上げた続編記事を探してみてください。

Service Fabric におけるステートフル マイクロサービスは、コンピューティングとデータを、その状態と共にマイクロサービス自体の内部 (メモリ内とローカル ディスクに永続化) に収容します。状態の信頼性は、ローカル永続化と、他のノード/VM へのデータのレプリケーションによって確保されます。基本的には、各データ パーティションに、複数のレプリカ サービスが関連付けられます。各レプリカをそれぞれ異なるノード/VM にデプロイして、プライマリ レプリカがダウンした場合の高可用性を実現します。これは、Azure SQL Database のデータベース レプリカ処理方法に似ています。と言うのも、Azure SQL Database は Azure Service Fabric をベースにしているためです。

複雑でスケーラビリティの高いアプリケーションでは、ステートフル サービスを使用することで、外部キャッシュとキューを使用する必要のある従来の 3 層アーキテクチャよりも、アーキテクチャが簡略化され、コンポーネントの数が少なくなります。ステートフル サービスを使用すると、従来の外部キャッシュを利用するメリットがステートフル サービスに組み込まれます。そのうえ、Service Fabric マイクロサービス内には内部キューを実装できるため、外部キューは必要ありません。

ステートフル サービスを使用すると、セカンダリ ホット バックアップが自動的に作成され、ハードウェア障害によってプライマリ システムが停止した場合、その時点から運用を引き継ぎます。増加するユーザーの需要を満たす場合は、運用環境にハードウェアを追加しながら、継続して何度もサービスをスケーリングする必要があります。Service Fabric では、パーティション分割などの機能を使用して、ユーザーの操作を必要としないで、新しいハードウェアにサービスが自動的に分散されるようにサービスをビルドできます。

ステートフル Azure Reliable Services は、データ パーティション サポート、レプリカ サポートとリーダー選出、レプリカ サービス、ゲートウェイ サービスからのサービス アドレス検出など、さまざまな機能のホストを提供します。また、トランザクションを使用した状態変化の同時実行と粒度の管理、一貫した状態レプリケーションの維持機能、および信頼性の高い分散キー/値コレクション (Reliable Dictionary と Reliable Queue) の使用も可能にします。さいわい、このようなタスクや機能の複雑な部分や細かい部分は Service Fabric によって自動的に処理されるため、開発者はアプリケーションの作成に専念できます。

Azure Service Fabric における Reliable Actors サービス

Azure Service Fabric Reliable Actors は、Service Fabric 用のアクター プログラミング モデルです。これにより、シングルスレッド非同期アクター モデルが提供されます (アクターは、状態とコンピューティングの単位を表します)。ある意味では、Microsoft Research が作成したオープン ソース ソフトウェア プロジェクトの「Orleans」に似ています。重要なのは、Service Fabric が提供する基盤インフラストラクチャが Service Fabric Reliable Actors API のベースになっている点です。

モノのインターネット (IoT) デバイスにアクター インスタンスを実装するのは、アクター サービスの利用を示す例の 1 つです。C# クラスの形式での Vehicle-Actor 型は、IoT 車両のドメイン ロジックとそのライブ状態 (GPS 座標など) をカプセル化します。その後、このクラスの何百万のアクター オブジェクトやインスタンスを、クラスター内の多数のノードに分散できるようになります。

もちろん、アクターはライブ IoT オブジェクトに限りません。どのようなサブジェクトにも使用できますが、説明には「ライブ IoT オブジェクト」が最適なシナリオです。

アクターは、クラスター全体に分散され、高いスケーラビリティと可用性を実現します。アクターは、すべてのクラスターの VM でインメモリ オブジェクトとして扱われます。また、ローカル ディスクに永続化し、クラスターを通じてレプリケートすることもできます。

アクターは、状態と動作をカプセル化する独立したシングルスレッド オブジェクトです。すべてのアクターは、次に示す .NET コードのように、アクター型のインスタンスです。

// Actor definition (State+Behaviour) to run in the back end.
// Object instances of this Actor class will be running transparently
// in the service back end.
public class VehicleActor : Actor<Vehicle>, IVehicleActor
{
  public void UpdateGpsPosition(GpsCoordinates coord)
  { 
    // Update coordinates and trigger any data processing
    // through the State property on the base class Actor<TState>.
    this.State.Position= coord;
  }
}

次のコードは、プロキシ オブジェクトを通じてアクターを使用するクライアント コードの例です。

// Client .NET code
ActorId actorId = ActorId.NewId();
string applicationName = "fabric:/IoTVehiclesActorApp";
IVehicleActor vehicleActorProxy =
  ActorProxy.Create<IVehicleActor>(actorId, applicationName);
vehicleActorProxy.UpdateGpsPosition(new GpsCoordinates(40.748440, -73.984559));

通信インフラストラクチャはすべて、Service Fabric Reliable Actors フレームワークが内部で自動的に処理します。

何百万もの VehicleActor オブジェクトを多数のノード/VM にまたがるクラスターで実行すると、Service Fabric は、何百万ものアクターが分散されるパーティション分割やレプリカなど、必要なプラミングを行います。

Actors クライアント API は、アクター インスタンスとアクター クライアント間の通信を提供します。アクターと通信するために、クライアントは、アクター インターフェイスを実装するアクター プロキシ オブジェクトを作成します。クライアントは、このプロキシ オブジェクトのメソッドを呼び出すことで、アクターとやり取りします。

アクターに適したシナリオでは、アクターを使用することで、マイクロサービスの実装が大幅に簡素化されます。ステートフル Reliable Services のように、細かく制御できても、データのパーティション分割、パーティション処理、レプリカなどに関連する多数のプラミングの実装が必要なものと比べた場合はなおさらです。きめ細かい制御が不要な場合は、Reliable Actors を使用することで余分な作業が不要になります。

まとめ

マイクロサービス アーキテクチャを実現するには、分散型アプローチ、秩序あるアーキテクチャと設計プロセス、Azure Service Fabric など、新しいテクノロジへの取り組みが必要です。また、小さな開発チームを目指すようにチームのダイナミクスを変化させ、アジャイル原則をマイクロサービスごとに適用する必要があります。


Cesar de la Torre は、マイクロソフトに勤務するワシントン州レドモンド在住のシニア プログラム マネージャーです。彼が注目しているのは、マイクロサービス アーキテクチャやドメイン駆動設計などのアプローチを使用した Microsoft Azure と .NET 開発、およびこうしたサービスとインターフェイスをとるモバイル アプリ開発です。

Kunal Deep Singh は、Microsoft Azure Service Fabric チームのシニア プログラム マネージャーです。Azure の前は、Windows Phone と Silverlight の複数のリリースの他、ゲーム開発者として Xbox タイトルに携わっていました。現在、ワシントン州シアトルに住んでいます。

Vaclav Turecek は、マイクロソフトのシニア プログラム マネージャーです。Azure Service Fabric を次世代最高の PaaS (サービスとしてのプラットフォーム) にするため、才能ある仲間と共に根気強く取り組んでいます。

この記事の共同執筆とレビューに協力してくれたマイクロソフト技術スタッフの Mark Fussell に心より感謝いたします。
Mark Fussell は、クラウドスケール アプリケーションの作成に情熱を傾けています。長年、マイクロソフトで、データ アクセスと通信、サーバー側テクノロジまで、さまざまな製品の作成に取り組んでいます。マイクロソフトが開発した Service Fabric を使用して、だれでもマイクロサービス アプローチによるアプリケーションのビルドができるようになることを喜ばしく思っています。