マイクロサービス – 分散された大きな泥だんご

モノリシックがダメだからといって、マイクロサービスが解決策になるわけではない

ソフトウェア開発業界は流行に左右されやすいという証拠に、今マイクロサービスが、いたるところで大騒ぎされています。”次の大ブーム”だと思う人もいるでしょう。また、(10年前に”上出来”と見なされたような)大型のSOA、サービス指向アーキテクチャが単に軽量化して進化したものだと捉える人もいるでしょう。私は現在のマイクロサービスアーキテクチャに関しては好意的に見ています。しかし、だからといってこのアーキテクチャは決して万能薬ではありません。言うまでもないことかもしれませんが、多くの人が間違った理由でマイクロサービスに飛び付いているように思えるのです。

これは私の講演でよくお見せするスライドで、以前ブログにも書きましたたが、ソフトウェアシステムを開発するにはいろいろな方法があります。まず、昔ながらのモノリシック(一枚岩の)システム。これは展開可能な1つのユニット内に全てがバンドルされているものです。おそらく業界の多くはこのシステムに関わっています。異論はあるでしょうが、モノリシックシステムは開発にかかる時間が短く、展開も容易です。ただし、アジリティ(機敏性)は劣っていて、ごくわずかな変更のために全面的な再展開が必要になってしまいます。もう1つ言えるのは、モノリシックシステムは、ソフトウェアが時とともに更新されるやり方が原因となってbig ball of mud(大きな泥だんご)になってしまいがちだということです。例えば、多くのモノリシックシステムは階層化アーキテクチャを使って開発されていますが、階層化アーキテクチャは乱用されやすい傾向があります(サービスを回避して直接データアクセス層/レポジトリを呼び出すなど)。

一方、サービスベースのアーキテクチャというのは、それぞれが個別に展開可能なサービス群によって構成されています。これについても異論はあるでしょうが、適切に構築すればフレキシビリティとアジリティは大幅に向上します。非同期メッセージングによってサービスが分離されている場合は特に顕著ですが、それぞれのサービスを個別に開発、テスト、運用、スケールアップ、アップグレード、リライトすることができるからです。マイナス面は、モノリシックシステムよりも多くの可動部分を持つことになり、複雑性が増すことです。Robertが言っているように、複雑性はよそに動かしただけにすぎず、依然としてそこにあるということになります。
もちろん、中間のやり方もあります。モノリシックシステムを開発する際に、明示的で適切なインターフェース及び責務を備えたインプロセスコンポーネントを用いるのです。これは昔ながらのコンポーネントベースの設計で、凝集度が高く結合度が低いという特性を持ちます。でも私はこの話をしようとする時、何だか躊躇してしまいます。変な感じがするのです。理由を説明する前に、まず今朝読んだブログの記事を引用させてください。この記事には、ある組織がマイクロサービス手法を採用する論拠について書かれています。

Karmaの開発を始めるに当たって、私たちはプロジェクトを大きく2つに分けることにしました。バックエンドのAPIとフロントエンドのアプリケーションです。バックエンドはストアから来るオーダーを扱い、利用課金、ユーザ管理、デバイス管理、その他もろもろの責務を負います。一方のフロントエンドは、ユーザがこのAPIにアクセスするダッシュボードを提供します。ここに至るまでの間に、バックエンドAPI全体をモノリシックにすると、すべてが絡まり合ってしまい、うまく機能しないことが分かりました。

このブログ記事では、マイクロサービスを選択するに至ったその他の理由として、スケールアップ、バージョニング、複数言語、複数フレームワークを挙げています。もう一度言いますが、万能薬はありません。すべてはトレードオフなのです。とにかく、”すべてが絡まり合ってきた”からといって、それがモノリシックからマイクロサービスに乗り換える理由にはなりません。モノリシックシステムを開発中に、絡まって大きな泥だんごになりつつあるのなら、ソフトウェアのアーキテクチャに十分な注意を払っているか考えるべきです。あなたが開発しているソフトウェアの中核となる構造抽象化は何なのか、本当に分かっていますか? インターフェースと責務は明確になっていますか? そうでないなら、なぜマイクロサービスのアークテクチャに変更すれば解決できると思えるのでしょう。確かに、サービスを物理的に分割することで、いくつかのショートカットを使わせないようにできます。でも、モノリシックのコンポーネント間でも同じように分割ができます。設計思想を入れて、明確なアーキテクチャのコーディングスタイルにすれば、問題をばらまくことなく解決できます。

私が今まで見てきた多くのチームはモノリシックなシステムを開発中で、コンポーネントベースの設計には見向きもしません。妥協点は見いだせそうにありませんでした。今年の初めに、あるチームと一緒にソフトウェアアーキテクチャのスケッチのワークショップを開催し、ソフトウェアシステムの1つを図にしました。そのシステム図は、初めは厳格な階層化アーキテクチャ(プレゼンテーション、ビジネスサービス、データアクセス)になっていました。すべての矢印は下を指し、それぞれの階層は、すぐ直下の階層しかコールしません。しかし書かれたコードは違うストーリーを示し、最終的なシステム図は、もはや整然としたものではなくなっていました。そこで私たちは、コンポーネント別のパッケージアプローチを採用することで、これを解決できないか議論しました。しかし出てきた答えは、「やっぱり階層化アプローチでソフトウェアを開発したい」というものでした。

チームはマイクロサービスがカッコいいからそれに飛び付いたかのようです。でも、優れたマイクロサービスアーキテクチャをつくる上で必要な設計思想と分散戦略は、優れた構造のモノリシックシステムをつくるために必要なものと同じなのです。もしチームが優れた構造のモノリシックシステムをつくれないのなら、彼らに優れた構造のマイクロサービスアーキテクチャがつくれるとは思えません。Michael Feathersが最近このように言っています。「それぞれのマイクロサービスの実装には、ある程度のオーバーヘッドがかかります。これがクラスのように簡単につくれるようになると、手の空いた人々は、トラブル、つまり桁違いに巨大なモノリシスを生み出すようになるでしょう」。同感です。大きな泥だんごが分散された世界、これが私の頭痛のタネなのです。