Microservices間通信における堅牢性原則

Microservicesを開発していく上で、堅牢性原則に則る方がそれぞれのサービスがより自律的になることがある。まずは堅牢性原則、Microservicesについて簡単に説明する。

堅牢性原則

堅牢性原則(Robustness Principle)とは、TCP/IP, SMTP, DNS, FTP, Telnetなどの開発者であるJon Postelが提唱した設計原則である。「送信するものに関しては厳密に、受信するものに関しては寛容に」という原則である。
TCPを規定した RFC793 において、相互運用性を担保するための性質を要約した以下の節が一般化されたようである。

2.10. Robustness Principle

TCP implementations will follow a general principle of robustness: be
conservative in what you do, be liberal in what you accept from
others.

Microservices

マイクロサービスアーキテクチャ』にマイクロサービスとは「協調して動作する小規模で自律的なサービス」であると定義されている。メンテナンス性の高さ、デプロイのしやすさ、スケーラビリティの高さ、障害の分離のしやすさなどがメリットとして挙げられる。
自律的であるためには、それぞれのサービスは凝集度が高く、結合度が低くなっている必要がある。自律的でないと、機能を追加したり、修正する際に複数のサービスに対してコードの追加・修正が発生し、単一サービスを独立してデプロイすることができなくなる。

また、「協調して動作する」は主にサービス同士が通信することを指しており、モノリシックなアプリケーションを開発するより、通信について考慮することが自然と多くなると思われる。

Microservicesへの堅牢性原則の適応

堅牢性原則に則り、「受信するものに関して寛容にしておく」ことで、あるサービスのAPIを修正した際に、そのAPIを呼んでいる別のサービス群を修正せずに済むケースがある。容易に実践できるものが2つある。

1つはresponseのアトリビュートが増えても、必要な分にだけ関心を持ち、増えた分を無視することである。
例として、あるサービスのAPIを修正し、戻り値のJSONの要素を増やした際に、そのAPIを呼び出すコンシューマー側のサービスが期待していたJSONとは異なるJSONを受けるケースを挙げる。この例では複数のコンシューマーのうち、あるサービスはfirstName、lastName、ageのみを必要としていて、emailは不要な場合を想定している。

emailという期待していない値は無視する実装にしていなければ、もともと修正したサービスに加え、コンシューマー側のサービスも修正することになる。
私の場合、静的型付け言語でClean Architectureに沿った実装をしていることが多いので、Driverのような外界との境界になるレイヤでJSONを受け、必要な要素(ここではfirstName、lastName、age)のみを型に詰めて、想定されていない要素を捨てている。

もう1つはrequestのアトリビュートに不足があったとしても、デフォルト値を設定し、補うというものである。
例えば、あるエンドポイントにOptionalでなく必須のクエリパラメータを追加してしまった場合、そのAPIを呼び出すすべてのサービスを修正する必要がある。複数のサービスを修正することになり、単一のサービスのみでデプロイできなくなる。
デフォルト値を設定しておけば、APIを呼び出す側のサービスの修正を防ぐことができる。あらゆるケースでデフォルト値を設定した方がいい訳ではないが、選択肢の1つとして考えるべきだろう。

堅牢性原則を適用した上で、あるサービスへの変更が起因となり、別のサービスも変更しないといけなくなることが何度もあるようであれば、サービスの境界分割をそもそも誤っている可能性がある。サービス間の結合度が低くないと、Microservicesの恩恵を受けることが難しいだろう。

参考

  • Microservices Patterns
  • マイクロサービスアーキテクチャ

Software engineer

Software engineer