最近のいくつかのブログ記事では、アプリケーションを4層アプリケーションアーキテクチャに基づき、複数のマイクロサービスの集合として開発、デプロイすることが重要だと考える理由を説明してきました。10年前には十分に機能していた開発プロセスやアプリケーションアーキテクチャを使い続けていては、増え続けるアプリの中から選べるモバイルユーザーの関心を引き付け、維持できるほど迅速に対応できないことが、ますます明らかになっています。
企業にとって、マイクロサービスアーキテクチャへの移行は、市場での新たな可能性を切り開きます。システムアーキテクトや開発者は、革新的なWebエクスペリエンスを顧客に提供するうえで、かつてないレベルの制御性とスピードを実現できる可能性があります。しかし、これほど目まぐるしいペースでは、失敗が許される余地はほとんどないと感じるかもしれません。現実には、プロセスを刷新している間も、アプリケーションの開発とデプロイを止めることはできません。将来の成功がマイクロサービスアーキテクチャへの移行にかかっているとしても、実際にはどのように移行すればよいのでしょうか。
幸いなことに、マイクロサービスを早期に導入した複数の企業が、オープンソースの精神に基づき、公開コードだけでなく、カンファレンスでの講演やブログ記事を通じて、その知見を惜しみなく共有しています。Netflixはその代表例です。Adrian Cockcroftは、Web Engineering担当ディレクター、続いてCloud Architectとして、100人のエンジニアがモノリシックなDVDレンタルアプリケーションを開発する従来型の開発モデルから、多数の小規模チームが数百のマイクロサービスをエンドツーエンドで開発するマイクロサービスアーキテクチャへの移行を指揮しました。これらのマイクロサービスは連携して、毎日数百万人のNetflixユーザーにデジタルエンターテインメントをストリーミング配信しています。現在、Battery VenturesのTechnology Fellowを務めるCockcroftは、マイクロサービスとクラウドネイティブアーキテクチャの著名なエバンジェリストであり、NGINX Technical Advisory Boardのメンバーも務めています。
全2回のブログシリーズでは、Cockcroft氏が昨年行った2つの講演から、特に重要なポイントをご紹介します。1つは10月に開催された第1回NGINXカンファレンスでの講演、もう1つはその数か月前に開催されたSilicon Valley Microservices Meetupでの講演です。(講演の全編を収録した「動画」も、ぜひご覧ください。)
- この記事では、マイクロサービスアーキテクチャを定義し、その設計に関するベストプラクティスをいくつか紹介します。
- Netflixにおけるマイクロサービス導入:チームとプロセス設計から得られた教訓では、ソフトウェア開発に対する新たな考え方を取り入れる理由と方法、そしてその考え方に基づいてチームを再編する方法について解説します。
マイクロサービスアーキテクチャとは
Cockcroft氏は、マイクロサービスアーキテクチャを「境界付けられたコンテキストを持つ、疎結合な要素で構成されるサービス指向アーキテクチャ」と定義しています。
疎結合とは、各サービスを個別に更新でき、1つのサービスを更新しても他のサービスを変更する必要がないことを意味します。小規模で特定の機能に特化したサービスが多数あっても、それらをまとめて更新しなければならない場合、疎結合ではないため、マイクロサービスとはいえません。マイクロサービスアーキテクチャへの移行時に見落とされがちな結合の1つが、データベース結合です。これは、すべてのサービスが同じデータベースにアクセスし、サービスを更新するとスキーマの変更が必要になる状態を指します。データベースを分割し、非正規化する必要があります。
「境界づけられたコンテキスト」という概念は、Eric Evansの著書『Domain Driven Design』に由来します。コンテキストが適切に境界づけられたマイクロサービスは、ソフトウェア開発において自己完結しています。マイクロサービスと他のマイクロサービスはAPIのみを介してやり取りし、データ構造、データベーススキーマ、その他のオブジェクトの内部表現を共有しません。そのため、他のマイクロサービスの内部について何も知らなくても、そのマイクロサービスのコードを理解し、更新できます。
インターネット向けアプリケーションを開発した経験があれば、名称は知らなくても、これらの概念はすでに実践を通じて理解しているはずです。ほとんどのモバイルアプリは複数のバックエンドサービスと通信し、ユーザーがアプリ内でFacebookに共有したり、Google Mapsで経路を検索したり、Foursquareでレストランを探したりできるようにしています。モバイルアプリがこれらのサービスと密結合している場合、アップデートをリリースする前に各サービスの開発チームと調整し、変更によって問題が発生しないことを確認する必要があります。
マイクロサービスアーキテクチャを採用する場合、社内の他の開発チームを、前述のインターネット上のバックエンドと同様に、マイクロサービスがAPIを介して連携する外部サービスとして捉えます。マイクロサービス間で一般に認識されている「契約」は、APIが安定しており、前方互換性を備えていることです。Google Maps APIが予告なく変更され、利用者のシステムに不具合を生じさせることが許容されないのと同様に、APIは進化させることができますが、以前のバージョンとの互換性を維持する必要があります。
マイクロサービスアーキテクチャ設計のベストプラクティス
Cockcroft氏は、Netflixのクラウドアーキテクトとしての自身の役割について、アーキテクチャを統制することではなく、Netflixのエンジニアが構築する過程で生まれたアーキテクチャを見いだし、体系化することだと説明しています。Netflixの開発チームは、マイクロサービスアーキテクチャの設計と実装に関するベストプラクティスをいくつか確立しました。
マイクロサービスごとに個別のデータストアを作成する
複数のマイクロサービスで同じバックエンドデータストアを使用しないでください。各マイクロサービスのチームが、そのサービスに最適なデータベースを選択できるようにする必要があります。また、単一のデータストアを使用すると、作業の重複を減らすという名目で、異なるチームが開発したマイクロサービス間でデータベース構造を安易に共有しがちです。その結果、あるチームがデータベース構造を更新すると、その構造を使用する他のサービスも変更しなければならなくなります。
データを分割すると、個別のストレージシステム間で同期のずれや不整合が生じやすくなり、外部キーが予期せず変更される可能性もあるため、データ管理が複雑になることがあります。不整合を検出して修正するために、バックグラウンドでマスターデータ管理(MDM)を実行するツールを追加する必要があります。たとえば、サブスクライバーIDを保存するすべてのデータベースを調べ、同じIDがすべてに存在すること(いずれのデータベースにもIDの欠落や余分なIDがないこと)を確認できます。ツールは独自に作成することも、購入することもできます。多くの市販のリレーショナルデータベース管理システム(RDBMS)でもこの種のチェックを実行できますが、通常はシステム間の結合に関する要件が多すぎるため、スケールしません。
コードの成熟度を同程度に保つ
マイクロサービス内のすべてのコードは、成熟度と安定性を同程度に保ちます。つまり、デプロイ済みで正常に稼働しているマイクロサービスのコードを追加または書き換える必要がある場合は、通常、既存のマイクロサービスをそのまま残し、新規または変更後のコード用に新しいマイクロサービスを作成するのが最善です。[編集者注:これは「イミュータブルインフラストラクチャ」の原則と呼ばれることもあります。]この方法なら、既存のマイクロサービスに障害やパフォーマンス低下が生じるリスクを負うことなく、バグがなくなり、効率が最大限に高まるまで、新しいコードのデプロイとテストを繰り返せます。新しいマイクロサービスが元のマイクロサービスと同程度に安定したら、両者が一体となって1つの機能を果たす場合や、統合によってほかの効率化が見込める場合には、再び統合できます。ただし、Cockcroft氏の経験では、マイクロサービスが大きくなりすぎたため、分割すべきだと気付くケースの方がはるかに一般的です。
マイクロサービスごとに個別にビルドする
各マイクロサービスが、それぞれに適したリビジョンのコンポーネントファイルをリポジトリから取得できるよう、マイクロサービスごとに個別にビルドします。その結果、複数のマイクロサービスが類似したファイル一式を異なるリビジョンで取得する場合があります。この場合、古いバージョンのファイルを廃止してコードベースを整理する際に、そのリビジョンが使用されていないことをより慎重に確認する必要があるため、作業が難しくなる可能性があります。しかし、新しいマイクロサービスを構築する際に新しいファイルを簡単に追加できることを考えれば、これは許容できるトレードオフです。この非対称性は意図的なものです。新しいマイクロサービス、ファイル、機能の導入は、危険を伴うのではなく、容易であることが重要です。
コンテナにデプロイ
マイクロサービスをコンテナにデプロイすることが重要なのは、すべてをデプロイするためのツールを1つに統一できるためです。マイクロサービスがコンテナ化されていれば、ツールはそのデプロイ方法を認識でき、コンテナの種類は問いません。とはいえ、Dockerは急速にコンテナの事実上の標準になったようです。
サーバーをステートレスとして扱う
サーバー、特に顧客向けコードを実行するサーバーは、グループ内で相互に置き換え可能なメンバーとして扱います。すべて同じ機能を実行するため、個々のサーバーを意識する必要はありません。必要な処理量を確保できる台数があればよく、オートスケーリングを使用して台数を増減できます。いずれかが停止した場合は、別のサーバーに自動的に置き換えられます。特定の機能を個々のサーバーに依存する「スノーフレーク」システムは避けてください。
Cockcroftのたとえでは、サーバーはペットではなく家畜のように考えるべきだとされています。本番環境に特殊な機能を担うマシンがあり、その名前を誰もが知っていて、停止すると皆が悲しむようなら、それはペットです。そうではなく、サーバーを牛の群れのように考えます。重要なのは、何ガロンの牛乳が得られるかです。ある日、牛乳の量が普段より少ないことに気付いたら、生産性の低い牛を特定して入れ替えます。
Netflixの配信アーキテクチャを支えるNGINX
NetflixはNGINX Open Sourceを長年利用しており、NGINX, Inc.が2011年に法人化された後、その最初の顧客となりました。実際、NetflixはNGINXを採用し、配信インフラストラクチャの中核に据えました。その配信インフラストラクチャであるOpen Connectは、世界最大級のコンテンツ配信ネットワーク(CDN)の1つです。NGINXとNGINX Plusは、毎秒数千件、場合によっては数百万件のリクエストを処理できるため、高パフォーマンスのHTTP配信に最適なソリューションであり、Netflixのような企業が毎日数百万人の顧客に高品質なデジタル体験を提供できるようにします。
動画録画
高速配信
nginx.conf 2014、2014 年 10 月
マイクロサービスへの移行、第1部
Silicon Valley Microservices Meetup、2014年8月
マイクロサービスへの移行、第2部
Silicon Valley Microservices Meetup、2014年8月
関連するブログ記事
チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。
AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。
JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。
F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。
NGINX PlusによるAWS Auto Scalingグループの負荷分散
新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります