見出し画像

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

マイクロサービスアーキテクチャとは何でしょうか。結構な誤解・誤用もあるように思えるので、私が実績から考えたマイクロサービスについて記載してみました。

マイクロサービスの間違った定義

Webや雑誌の記事、お客様の会話からすると、マイクロサービスアーキテクチャの定義がまちまちで、モヤモヤするところが多分にあります。確実に間違っている定義はこちらではないでしょうか。

  • 既存の機能をAPI経由で呼び出す

  • 画面遷移を考慮し、一連のアプリケーションを機能単位で切り出す

  • 各業務をまたがる共通機能をマイクロサービスとして利用する


既存の機能をAPI経由で呼び出す

これは西暦2000年頃に流行した、「Service Oriented Architecture (SOA)とは、WebServiceを使うこと」という誤解に近いです。マイクロサービスアーキテクチャというのは概念であり、実装の手段を定義したものではありません。現行の機能をAPIで呼び出すという考え方は、利用形態としてはゼロではないと思いますが、時々見かけるのは、モノリスの考え方で作られたアプリそのものをAPI化している例です。これは手段について行っているのであって、概念的にはモノリスに蓋をしているのではないでしょうか。
社内の特定のアプリでしか使わない機能をAPI化することは、余計なソースが増え複雑さが増し、障害を起こしやすくしているとしか思えません。
マイクロサービスとして「役割に応じたAPI」を定義し、各アプリがそれを利用すると言う意味であれば、それは良い方法ですが、あくまでも「業務に対する役割」という観点が必要です。

画面遷移を考慮し、一連のアプリケーションを業務機能単位で切り出す

業務単位で切り出すというところは、モノリスアプリを単にAPI化するよりもまだ良いと思います。しかし、使っていない機能などもそのまま移行されてしまう傾向にあり、不必要なソースが多く残ってしまいがちです。さらに、画面、データ、ロジック、データが渾然一体となった状態のアプリであるとすると、切り離されたアプリとの連携、データの連携がより複雑化する傾向にあります。私はこの状況を「マイクロモノリス」と呼んでいますが、技術的負債の解消には程遠く、あまり良い手段とは思えません。

各業務をまたがる共通機能をマイクロサービスとして利用する

共通と思っていても実際にはある業務だけで例外を作っていたりすると、もはや共通部品という概念すら成り立たなくなってしまい、変更したい特に容易に変更できない仕組みが出来上がってしまいます。そうなると、共通機能が極小化して関数レベルになりがちで、マイクロサービスという粒度としては細かすぎる傾向になります。
また、業務をまたがる不変な部分、例えば郵便場号から住所を取り出すなどのサービスを共通化するのであれば、それはマイクロではない単なるサービス(例えば郵便番号からの住所補完サービス)でよいのではないでしょうか。
マイクロサービス化は共通機能の外出し化ではありません。

マイクロサービスの良い定義

では、マイクロサービスとはどういう定義にするとよいのでしょうか?

ITとしてのサービス

上記の反例で挙げた中で明らかに欠如しているのは、「ITとしてのサービスの考え方」です。そもそも「サービス」とは、あるリクエストをするといくつかの操作や手順をまとめて行って、期待している答えを返してくれる塊のことを指します。一般的に業務アプリケーションにおいては、データとロジック・ステータス管理・画面・帳票 などで構成されていますよね。画面はデータの入出力をするものであり、ユーザーインターフェースの役割と考えるとUser Interface Serviceと定義することが出来ます。同様にして、チェックや計算・推論はディシジョンサービス、担当者が抱えている処理すべき案件のリストの提供・承認却下行為を管理するものとしてプロセスサービス、データを保管したり必要なタイミングで取り出すデータサービス等と、ITとしてのサービスを定義すると良いです。

ITとしてのサービス例

ITとしてのサービスの概念をあまり細かくやっても収集がつかなくなるので、図のような5−6個のサービスと捉えておくと良いと思います。そして、ディシジョンサービスからデータサービスを直接呼ばないようにします。「DBに格納されているマスターテーブルを参照して値を決定する」という実装は、心を鬼にしてやりません。あくまでも、データサービスに問い合わせをして得られたデータと判断すべきデータをデシジョンサービスに渡して、結果をもらいます。

一見すると、面倒な処理に見えるしメモリも多く使う様に思えます。しかし、ここが大変重要な肝なのです。DBのマスターテーブルを参照するようなロジックだと、マスターに書けないような例外処理のために別のマスターテーブルが用意される、例外ルールがアプリの中に実装される などで、あっという間にメンテナンスができなくなるスパゲッティ状態のアプリケーションができてしまいます。コレを防ぐためには、それぞれのサービスの役割を明確にし、自分の役割を超えたことをさせないようにすべきなのです。

これこそが、Service Oriented Architectureなのです。

ITとしてのサービスと業務の交差

ITとしてのサービスを固めた上で業務(ドメイン)という軸を考えてみると、単純に縦にさせば、それ自身が業務アプリケーションとして成り立つことはご理解いただけると思います。そして、横のITとしてのサービスと業務が交わったところ、一つ一つがマイクロサービスであると定義してはいかがでしょうか。

ITとしてのサービスx業務=マイクロサービス

例をあげるとすると、製造業においては顧客の登録、見積書の作成、在庫の引き当て、請求書の発行、配送、回収等が業務の軸であり、その一つ一つの業務は、画面、データ、プロセス、ルール等で構成されていることが理解できると思います。マイクロサービスとして定義するものは、顧客の登録という業務の画面、顧客の登録という業務のタスク管理、顧客の登録という業務のチェック... となります。夫々のサービスの役割は明確でかつ他のサービスとかぶることはありません。各サービスを連携するものこそが「アプリケーション」という位置付けになります。

ではこのままでマイクロサービスとして定義してよいかと言うと、現実はそうでもありません。更に細かくなるのが一般的です。下記は受付業務をもう少し分析したものになります。

マイクロサービスの粒度の例

受付業務は、会員登録、審査、ご案内通知 という3つのタスクに別れているとします。それぞれのタスクで必要なサービスをマップしてみると、歯抜けになっているところがありますよね。しかし、どのタスクであれ、必要とするサービスが「たまたま無い」だけなので、アーキテクチャとしては包括的なサービスの概念でよいのです。

各タスクとサービスが交わるところで、実際に何をするのかを記載したものが下記になります。

マイクロサービスの粒度と役割の例

それぞれ異なる仕事をしています。この単位で一つのマイクロサービスという粒度にしていくことが望ましいです。細かくしすぎると煩雑になるし、粒度が大きすぎると役割が曖昧になってしまいます。粒度は何回かの試行錯誤で調整していきます。

ココで一点、注意することがあります。プロセスサービスの位置付けです。
この例で言うと、会員登録、審査、ご案内通知という横の動きが「ビジネスプロセス」であり、縦の動きである「サービスの呼び出し」は、サービス間連携となります。

ビジネスプロセスとサービス間連携いの違い

今までのBPM製品の使い方はよろしくないと思っています。というのも、サービス間連携の部分までもBPMでやっている傾向があります。トランザクション処理をBPMでやらせてしまうと、外部システムへの連携のような疎結合連携までもRollbackさせることは至難の業であり、不具合の多発や性能劣化が頻発します。横の動きと縦の動きを別々に考え、横の動き、すなわちビジネスプロセスのみをBPMで管理することを強くお勧めします。

マイクロサービスの実装

そして、会員登録部分の実装イメージは下記のようになります。
右側に記載しているのが、実際のアプリケーションであり、各サービスの呼び出し順序を制御するものになります。呼び出される各サービスは、RESTなりPOJOなりの実装で、プロトコルは問いません。好きなものを使ってください。複数のDBへのコミット等、トランザクション処理が必要であれば、このアプリケーションの部分(図の右にある縦のグレーな長方形、すなわち図の左にある「会員登録」の流れ)で実装します。

各サービスの呼び出し方

更に、各マイクロサービスで作られたアプリケーションは、Queueを介してデータをやり取りするようにすることで、処理の負荷集中によるスループットの低下という問題に対して、多重化して回避することが容易になります。いわゆる疎結合化です。
一方で、Queueを用いるということは、データの入力に対してパーシスタンスであるDBなどと非同期処理となります。厳格なデータの順序性を担保するには同期処理が必要となりますが、データの使い方を見直し、1-2秒の遅延やデータの追い越しがあっても、データを使う時にソートするなりで結果整合性を許容できるとなると格段に適用範囲は広くなります。また、更新後即時に参照しなければならないデータであれば、DBの前にインメモリデータベースにも格納してキャッシュとして利用し、パーシスタンスを伴うDBへの書き込みは背後で多少の遅延をもって行う等の方策も有効となります。

まとめ

おさらいすると

  • マイクロサービスの定義は、ITとしてのサービスと業務の掛け合わせの一つ一つとして定義すると良い

  • マイクロサービスの実装では、意思決定を行う部分とデータのアクセス部分は分離させる

  • ビジネスプロセスとサービス間連携は意味合いが異なるため、別々の作りとする。

  • Queueをうまく使い疎結合化を行うことで、負荷への柔軟性や運用容易性を得る

いかがでしたでしょうか。マイクロサービスの定義をきちっと行うと、ごっちゃに考えがちな業務を切り分けることが自然にできるようになり、全体がシンプル化していきます。実装面では自動的にイベント・ドリブンなアーキテクチャになっていきますので、今までのバッチ処理の課題がかなり解決していきます。開発手法もアジャイルなやり方の方がマッチするようになります。また、マイクロサービス化されることで、コンテナ環境を効率よく使うことができるようになります。

マイクロサービス化。オススメなので一度ご検討してみてはいかがでしょうか。


この記事が気に入ったらサポートをしてみませんか?