はじめに
これまでの記事で、@takahashisansan の記事「マイクロサービスが開発・運用コスト削減におよぼす効果」や、@tsukmrの記事「マイクロサービス化で直面するサービスの分割」を考えてきました。
システムによっては一から新しいアーキテクチャで開発を始めることもありますが、既存のモノリシックなシステムから新しいアーキテクチャで構築されたシステムに置き換えていくこともあって、その新しいアーキテクチャとして、柔軟性の高いマイクロサービスが選ばれることも多いと思います。
そこで今回は、実際に既存のモノリシック(Monolithic)なシステムを柔軟性の高いマイクロサービス(Microservices)のようなシステムに置き換えていくにあたって、どのようにしていけばよいかを考えてみました。
マイクロサービス化の移行パターン
Sam Newmanが著している「Monolith to Microservices」によると、このような置き換えにおいては以下の6個のパターンがあるとしています。
- Strangler Fig Application
- UI Composition
- Branch by Abstraction
- Parallel Run
- Decorating Collaborator
- Change Data Capture
このうち新しいシステムに置き換わっていく様子そのものを示していて一番抽象度の高い概念と考えられるStrangler Fig Application(以下、「ストラングラーパターン」と記載します。)と、実際にストラングラーパターンを実現するための一つの具体的な技術と考えられるBranch by Abstraction(以下、「抽象化による分岐」と記載します。)をまずは選んで調べてみました。
ストラングラーパターンとは?
2004年にMartin Fowlerによって、大規模なWebアプリケーション内のソースコードをリファクタリングしてリリースする際の処理方法として定義されたパターンが、ストラングラーパターンと呼ばれるものです。この時には、リファクタリングの際に使用することが想定されていましたが、リファクタリングの時だけではなく、既存のモノリスアーキテクチャからマイクロサービスアーキテクチャに移行する際にも有効と考えられています。
大規模なソフトウェアに、例えば新たな機能を追加するのに一部のソースコードを書き換える場合、ストラングラーパターンと呼ぶかどうかは別として、同じような考え方が適用されていると思います。
文字通り「絞め殺しの木(Strangler Fig)」が、他の植物に巻き付いて、その植物を絞め殺しながら自分が成長していく様子が、システムが新しいアーキテクチャに置き換わっていく様子に似ているということで、この名称がつけられているとのことです。
最初は全てが既存のモノリシックなシステムであったのが、時間が経つに従ってモノリシックな部分がシュリンンクしていき、代わって新しいシステムを構成するStrangler Applicationが成長していき、最後にはすべてStrangler Applicationに置き換わっていきます。
実際にモノリシックなシステムを構成する一つの機能がどのように新しいシステムに代わっていくのかは、下図が示しています。
下図では三つのステップを経て新しいシステム(新しいアーキテクチャ)に置き換わっていきます。
- 機能の特定:既存のシステム(Monolith)において、新しいシステム(Microservice)に移動させたい機能を特定します。
- 機能の実装:新しいシステム(Microservice)上に、先に特定した機能を実装します。
- リダイレクト:実装の準備が出来たら、機能の呼び出しを既存のシステム(Monolith)から新しいシステム(Microservice)に変更します。
図はSam Newmanの「Monolith to Microservices」のFig 3-1をベースとして一部加筆しています。
ストラングラーパターンのメリット
ストラングラーパターンにおいては、全ての機能を一気に置き換えるのではなく、徐々に置き換えていくことになるため、必要に応じて軌道修正・方向転換を簡単に行うことが出来ることがストラングラーパターンを用いるメリットになります。
また、徐々に置き換えていくために、優先度付け・重要度付けを行って対応する(優先度によっては移行しないこともあります。)ことが出来ることもメリットになります。
抽象化による分岐について
Paul Hammantによって名付けられたものですが、Martin Fowlerによると目新しい技術ではないようです。ソフトウェアへの大規模な変更を徐々に加えていく時に使われる技術です。抽象化層を設けて、その層を経由しながら段階的に変更を加えていくことになります。
下図では六つのステップを経て新しいシステムに置き換わっていく様子を示しています。
Step2: 既存のクライアントのコードを抽象化層を経由するように変更します
ここでは、まず最初に支払機能を抽象化したものを使うようにし、その後、請求を抽象化したものを使うように変更します。
Step3: クライアントに必要な機能を実装した新しいモジュールを作ります
Step4: 新しいモジュールを使うように切り替えます
Step5: Clean upとして、まず古いモジュールを削除します
Step6: Clean upとして、次にStep1で新たに作った抽象化層を削除します。
図はSam Newmanの「Monolith to Microservices」のFig 3-22~Fig 3-28をベースとして一部加筆しています。
これを見ても分かるように、ストラングラーパターンが大きな概念で、それを実現するための一つの技術が抽象化による分岐と考えた方がよいでしょう。
さいごに
この検討を行ったメンバーに、過去のエンベデッドシステムの開発経験者がいて、以下のようなコメントが出ていたので引用しておきます。
「振り返ってみると、当時はストラングラーパターンという名前では呼んでいなかったものの、過去に行ったエンベデッドシステムのソフトウェアの開発でも同じような方法で行っていたと、今さらながらですが気がつきました。
例えば、デバイスを制御して機能を実現するようなソフトウェア開発では、新しい機能を追加したソフトウェアを開発するときに、新しいソフトウェアで制御するデバイスは何かを抽出し、その中で新規デバイスが何になるのかを抽出し、その新規デバイスの制御部分を実装し、既存のデバイスに対する制御から新しいデバイスに対する制御に切り替えていました。
大規模なソフトウェアを新しいシステムに置き換えていくような場合や新機能を追加していく場合、名称は別にして、リスクを軽減し、開発費を抑えたいということがあるためにストラングラーパターンにより実現していると言えるのではないかと思いました。」