Service Discovery Patterns
Microservicesを導入すると、以下のようなメリットがあります。
- 機能追加が容易になる
- 可用性・耐障害性が向上する
- スケールアウトが容易になる
- 新技術を導入しやすくなる
- DevOps/Agileとの親和性が高い
しかし、Microservicesの導入により、いくつか課題が発生します。そのうちの1つであるService Discoveryについて書きました。
Service Discovery
Service Discoveryとはデプロイされたアプリケーションがどこにあるかを見つけ出すしくみのことです。Service Discoveryという言葉に慣れ親しんでいない人でも、なんらかの方法でサービス間の呼び出しを実現しているはずです。例えば、hostsファイルでサーバー名とIPアドレスをマッピングしたり、DNSでドメイン名とIPアドレスをマッピングしたり、サービスのIPアドレス固定して、そのIPアドレスを設定ファイルなどに直接書いたりすることが考えられます。
現代のVMやコンテナを用いたクラウドベースのアプリケーションでは、IPアドレスが動的に割り当てられます。そのため、クライアントは対象のサービスインスタンスのIPアドレスをリアルタイムに検出する必要があります。この問題を解決するのがService Registryです。これはサービスインスタンスのネットワーク上の位置が格納されたデータベースです。サービスインスタンスが起動・停止したタイミングなどでService Registryが更新されます。そして、クライアントはService Registryのデータをもとに、リクエストしたいアプリケーションの位置を見つけることができます。
このようなService Registryを用いた動的なService DiscoveryはApplication-level service discovery patternとPlatform-provided service discovery patternに大別できます。それぞれのパターンについて書いていきます。
Application-level service discovery pattern
このパターンはアプリケーションにService Discoveryを実装したパターンです。アプリケーションレイヤでのService Discoveryは次のような流れになります。
サービスクライアントは、最初にService Registryにサービスインスタンスの位置のリストを問い合わせます。 そして、それらのサービスインスタンスの1つにリクエストします。NetflixのEureka、Ribbonがこのパターンに該当します。※1
このパターンはSelf Registration patternとClient-side service discovery patternを組み合わせたものです。Self Registration patternとClient-side service discovery patternそれぞれについて説明します。
Self Registration pattern
サービスインスタンスが自らService Registryにホスト名とIPアドレスを登録します。また、サービスインスタンスが停止やクラッシュしたり、起動中であるもののリクエストを受けることができなくなったりした場合は自らをService Registryから削除します。
Client-side service discovery pattern
クライアントがサービスインスタンスにリクエストしたい際、まずService Registryに問い合わせてサービスインスタンスのリストを取得します。その後、クライアントは取得したリストからサービスを選択し、そのサービスにリクエストします。パフォーマンス向上のためにサービスインスタンスのリストをキャッシュしておくこともあります。
Platform-provided service discovery pattern
このパターンはService DiscoveryはService RegistryとService Discoveryの機構がデプロイメントプラットフォームに組み込まれたパターンです。
まず、デプロイメントプラットフォームに属するRegisterがサービスインスタンスをService Registryに登録します。そして、クライアントがルーターにリクエストし、ルーターはすでに登録されたService Registryの情報をもとにサービスインスタンスに受けたリクエストを転送します。
ここでの、Service Discoveryやルーティングなどはデプロイメントプラットフォームが担っています。AWSやGCPなどのクラウドサービス、Kubernetesのようなコンテナオーケストレーションシステムを利用している場合、イメージしやすいでしょう。
このパターンは3rd Party RegistrationパターンとServer-side service discoveryパターンを組み合わせたものです。3rd Party RegistrationパターンとServer-side service discoveryパターンそれぞれについて説明します。
3rd Party Registration pattern
デプロイメントプラットフォームに属するRegistrarがService Registryへサービスインスタンスの登録・登録解除を行います。
サービスインスタンスをオートスケーリングさせている場合、サービスインスタンスが増えれば、そのサービスインスタンスがService Registryへ登録され、サービスインスタンスが減れば、そのサービスインスタンスがService Registryから削除されます。また、Registrarが各サービスインスタンスにヘルスチェックを行い、その結果に基づいて登録・登録解除を行うこともあります。
3rd Party Registration patternを適用すれば、Self Registration patternのようにアプリケーション本体にコードを書く必要がなくなります。
Server-side service discovery pattern
クライアントはルーターに対してリクエストするだけで、ルーターがサービスインスタンスにリクエストを転送します。
Server-side service discovery patternは Client-side service discovery patternと違って、クライアントがサービスインスタンスを意識する必要がありません。また、ロードバランシングの役割はルーターが担うことになります。
所感
アプリケーションが特定のプラットフォームに閉じ、そのプラットフォームへの依存を許容できるのであれば、Platform-provided service discovery patternを採用した方がよいと思います。アプリケーションがどんな言語で実装されているかを意識する必要がないですし、アプリケーションのコードを減らすことができます。Application-level service discovery patternを採用すれば、Microservicesそれぞれによく似たService Discoveryのコードを書く必要があります。
参考
※1 Ribbonはこのブログを書いている2019年3月2日時点でメンテナンス中になっています