どこにでもいるSEの備忘録

たぶん動くと思うからリリースしようぜ

【読んでみた】マイクロサービスアーキテクチャ

この前はこんな本を読んでいました。

nogawanogawa.hatenablog.com

この本の中で

しばしば、マイクロサービスアーキテクチャは、小さなサービスに分割するという技術的な潮流として理解されることが多いですが、実際には、いかにして技術組織の情報処理能力を上げていくかという組織論の問題でもあります。

と書かれています。

これからの時代アーキテクチャとしてマイクロサービスは必須だろうと感じてますし、組織論的にも必要と言われたら導入するしかない! ってことでこちらの本を読んでみました。

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

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

マイクロサービスについては、構想から設計・実装までちゃんとできるくらいちゃんと知っといて損はないと思ってます。 てなわけでやっていきます。

tl; dr;

  1. マイクロサービスとは、協調して動作する小規模で自律的なサービス。特徴は
    • 小さく、かつ1つの役割に専念
    • 自律性
  2. 境界付けられたコンテキストで十分にサービスを小さく分解する。ポイントは
  3. サービスの結合方法は、共通かつシンプルにする。できればRESTを検討すること。
  4. 開発はとにかくCI・CDを使うこと
  5. マイクロサービスの良さを消さないようなテスト戦略を組むことが望ましい
  6. サービスが多数存在することが想定され、それらを統合管理していく仕組みが必要
  7. 認可と認証についてのサービスを組み込むこと
  8. 大規模になったら、サービス間の応答や耐障害性を考慮して適切にスケールすること

マイクロサービスとは

まず、そもそものマイクロサービスの定義を確認します。

マイクロサービスとは、協調して動作する小規模で自律的なサービスです。

特徴としては以下の二つらしいです。

  • 小さく、かつ1つの役割に専念
  • 自律性

サービスが小さいことと、自律していることは特徴であってメリットではありません。

マイクロサービスのイメージとしてはこんな感じでしょうか?

f:id:nogawanogawa:20190427223942j:plain:w500

各サービスが一つの役割を担い、自律的に可動できるようにしていきます。

メリットはこんな感じです。

  • 技術的異質性
    • サービスごとに異なる技術要素を自由に決められる
  • 回復性
    • あるサービスがダウンしてもその他のサービスで稼働し続けられる
  • スケーリング
    • 必要なサービスを必要なだけスケールさせることが可能
  • デプロイの容易性
    • 更新したサービスだけデプロイしなおせば全体として稼働し続ける
  • 組織面の一致
    • 多くの場合、組織構造と思想が合致する
  • 合成可能性
    • 既存のサービスを簡単に新しいサービスに組み込むことが可能
  • 交換可能のための最適化
    • 新しいサービスに、部分的に置き換えていくことが可能

メリットだけ見ると、理想形ですね。 ただ、こんなことも本に書いてあります。

本章を締めくくる前に、マイクロサービスは無料の昼食でも銀の弾丸でもなく、金のハンマーとして使うと好ましくない選択になることを指摘しなくてはなりません。

メリデメをきちんと把握したうえで、ちゃんと使いましょうってことです。

なぜ必要か?

そもそも、なんでマイクロサービスが必要となっているかという話です。

この辺はアジャイルの生い立ちと絡んでいて、プロジェクトは計画通りに進まなければ、作ったものを更新し続けることが当たり前になっているからだと思っています。

アーキテクト(建築士)という肩書があったりしますが、建築とは似ても似つかず、事前にすべてを計画しつくすことはほぼ不可能です。 なので、変更に耐えうるアーキテクチャが必要になるから、マイクロサービスが必要なんだと思っています。

実現するための考え方とかについては本書をぜひ読んでください。

マイクロサービスの境界線を探す

どうやらマイクロサービスを設計する上でのポイントは、疎結合高凝縮性のようです。 何かを修正したい場合に、一つのサービスだけをビルドし直してデプロイするだけで良くなっていれば、サービスのリリースは頻繁に行うことができるはずです。 また、何かの機能を修正しようとしたときに、対象となるサービスが1つであれば、エンジニアはそこだけを注目して開発に集中できます。

これができるようにマイクロサービスの境界線を考えていくのがポイントです。 あくまで前提にあるのは、あとで追加・修正しやすいことですね。 その上で、一般的には組織構造に着目してサービスを切り分けていくようです。

マイクロサービスをやっていく上で一番のテーマになるのはどこで区切るかになるんでしょうね。

設計指針

さて、少しずつ細かい設計を見ていきます。

どうつなぐか?

まず困るのは、マイクロサービス間をどうつなぐか?ということです。

設計の際の思考のプロセスとしてはこんな感じでしょうか。

f:id:nogawanogawa:20190427223922j:plain:w500

まず原則として、DBをマイクロサービス間で共有することは避けたほうが懸命です。 これは疎結合と高凝縮の原則に反しており、修正箇所が膨れ上がる原因になります。

次に考えるべきは、同期通信か非同期通信かです。 理想論で言えばイベント駆動で非同期通信を選択するのが望ましいと考えられますが、実際には同期通信が選択されるケースがほとんどな気がします。 非同期通信だと、不具合を見つけるのに苦労することが多い気がしますし。

同期通信でも、RPCかRESTかという選択肢が考えられます。 これもケースバイケースといえますが、一般にRPCの方が技術要素に対する依存性が強く、技術要素の更新が必要になる場合に大掛かりな修正が発生することが考えられます。 そのため、RESTが選択されることが多い気がします。

ユーザーとマイクロサービス間はどうでしょう? 最近の流行りとしては、SPAがトレンドになっている気がします。 さらに、フロントエンドのデバイスに表示が依存する場合には、本書のようにフロントエンド向けのバックエンドを用意することが良いのかもしれないです。

f:id:nogawanogawa:20190427223904j:plain:w500

その他、使用するサードパーティ製のツールを含め、アーキテクチャは様々考えられますが、 大事なのは各サービスにおける機能の凝縮性を担保していくことですね。

どう分解するか?

次に、大体の場合すでに稼働中のサービスがあったりします。 そこからマイクロサービスに移行することを考える際には接合部を意識する必要があります。

接合部の決め方は人それぞれです。 本書では、境界付けられたコンテキストの単位で分解することが、高凝縮性・疎結合を高めるのに有効と考えています。

明示的な境界によって強制される特定の責務

この手の話を考えると、DBの存在が厄介になってきます。 ポイントはマイクロサービスがアクセスするテーブルを、ほかのマイクロサービスからアクセスできなくするように、テーブルを切り分けることです。

感覚としては、同じテーブルを複数のサービスが参照するような場合には、テーブルを分割するか、サービスに問い合わせを行うように変更するか、サービスとDBの間に新しい参照用サービスを作るか、というような形で分離していきます。 どの手法をとっても更新処理は複雑になります。 この辺は難しいので、本読んでください。

開発

テスト

テストは、マイクロサービスに限らず厄介な問題で、何をどれだけやるかを検討していく必要があります。 マイクロサービスのテストのポイントは、マイクロサービスの良さを消してしまわないようにテスト戦略を組むことだと思います。 いろんな手法がありますが、そのトレードオフをきちんと考えた上で最善の選択をする必要があるのかなと思います。

テストについては、今度別の記事でちゃんとやろうと思います。覚えてたら。。。

デプロイ

開発に注目したとき、マイクロサービスはCI・CDを使用して運用されていくことが望ましいです。 というか、不具合を早期に検知するためにはそれがほぼ必須になってきます。

CIを行うときには、各サービスをどう管理・テスト・ビルドするかの戦略はきちんと考える必要がありそうです。 規模が小さければ、すべてのマイクロサービスを一つのリポジトリで管理し、すべてのテストを同時に実行することが最も簡単です。 一方で、全体の規模が大きくなってきた場合には、マイクロサービスごとにリポジトリ管理し、個別にビルド・テストしていくことになります。 新規に作るにせよ、既存のプロダクトに改修を行うにせよ、ビルドパイプラインの設計が重要になりそうですね。

この手の話で問題になってくるのが、環境構築の所要時間と環境の整合性でしょうか。 Ansibleのような構成管理ツールを使うにせよ、Dockerのようなコンテナを使用するにせよ、開発サイクルにおけるデプロイの時間は注視する必要がありそうです。

環境の管理については、いまどきはもうDockerなんでしょうね。

監視

監視については、マイクロサービスにするとみるべきものが増えるので、さまざまなログを一か所にまとめることが望ましいです。 この本ではLogstashログを集約してますね。 やり方については、この辺が参考になるかと。

www.elastic.co

www.elastic.co

www.elastic.co

集約するだけだと手におえないので、ダッシュボードにまとめるのもお忘れなく。。。

最近、監視についてこちらの記事が話題になってました。

blog.song.mu

blog.song.mu

監視についても考えていかないといけないですね。だいぶ先になりそうだけど、ちゃんと勉強しようかなあ。。。

セキュリティ

セキュリティは、はっきり言って全然わかってないっす。 外部からの攻撃に対する方針など、組織ごとに異なるかと思いますので、その辺は勝手にやればよいのではないでしょうか?

マイクロサービス的な観点で言うと、認証用のサービスを使って、各サービスで認証情報を取り扱う仕組みを導入していくことが必要になってきます。

非機能要件

耐障害性については、一般的な話なので割愛します。 モノリシックだろうとマイクロサービスだろうと、基本は変わりません。 適切に障害時の挙動を検討していくことに変わりはありません。

マイクロサービスで問題になるのは、サービスの数が増えることによるスケーリングの問題だと思います。 まずサービス間通信に関する問題ですが、こちらはビジネス要件と照らし合わせて考えます。 本当に速度が必要な場合は対応がキャッシングなどの対策が必要ですが、今時そんなシステムはそこまで多くないので。 やりすぎは時間と労力の無駄です。

あとは分散処理ですが、これも一般的なシステムと変わんないですね。 負荷やリスクに応じた分散配置戦略を適用していくだけです。

その他、DBとかのレプリケーションの話とかありますが、当たり前すぎて割愛します。 この辺はその道の人のほうが詳しいですね。

感想

流行りだからとか、クラウドが当たり前の時代だからとか関係なく、モジュールを疎に結合させるというのはプログラミングにとって基本だと思います。 そういう意味では、マイクロサービスは流行るべくして流行っているという風に思ってます。

実際のマイクロサービスを手を動かして勉強する際には、こちらの記事にあるようなリポジトリが使えそうです。

kakakakakku.hatenablog.com

今度触ってみたいと思います。