サーバーサイドのWebアプリケーションアーキテクチャ
かめです。
去年11月に入社して3ヶ月が経とうとしていますが、楽しくやれています。
私はWebアプリケーションのシステム全体を見る様なアーキテクトとしてのスキルを磨きたくてDWSに入社したわけですが、元々組み込み系出身でWebアプリケーションのアーキテクチャについてはあまりわかっていません。
そういうことで今回は勉強がてらサーバサイドのWebアプリケーションアーキテクチャについて調べてみました。
そもそもソフトウェアアーキテクチャとは
これはかなり私の主観が含まれますが、ソフトウェアアーキテクチャの本質とは「ソフトウェアがスムーズに品質よく開発できる状態にすること」だと思っています。
そのためにすることは、綺麗な設計にすることはもちろんなのですが、ソフトウェアを開発する組織の組み方やコミュニケーションプラン、開発プロセスなども含んで最適に組み上げられたものでなければならないと思っています。
ただこれは理想論として思っているだけで、「じゃあどうすればいいんだみたいな」一般論を持っているわけではなく、主に組織のカルチャーや構成、組織のガイドラインなどに応じて泥臭く改善していかないといけないのかなと思っていたりします。
なので今回は、そういったことではない一般的なソフトウェアアーキテクチャについて、さらにその中のサーバーサイドのWebアプリケーションにおけるアーキテクチャについて調べてみた、という話になります。
サーバーサイドのWebアプリケーションアーキテクチャについて
サーバサイドWebアプリケーションのアーキテクチャ、といっても結構広範囲になるわけですが、そのアーキテクチャも細分化すると以下の様な感じで分けられるかと思います。
- サービスの分割の方針
- サービスの分割手法
- 単一サービス内部の構成
- それを支える技術
これらを紹介するだけでも結構長くなりそうなので、今回のブログポストでは「サービスの分割の方針」についてご紹介します。「サービスの分割手法」「単一サービス内部の構成」「それを支える技術」についてはまた後日投稿したいと思います。
サービス分割の方針
一つのシステムを開発する際に、可用性や保守性の向上を目的に、システムを複数のサービスに分割することがあります。
その分割の仕方の方針として、以下のようなものがあります。
- モノリシック
- マイクロサービス
- モジュラーモノリス
- ミニサービス
モノリシック
サービス分割なんて考えないで、一つのサービスで全部作っちゃおうぜ!という考え方です。
サービス分割を考えない分、短期的な開発効率はとても高いものとなります。
そもそもサービス分割を行う目的は、上記でも述べた通り可用性や保守性の向上が目的となりますが、プロジェクトの状況によってそういった点には目をつぶり、開発スピードを優先したい場合に用いられます。
マイクロサービス
出ました私の好きなマイクロサービス。
システム全体を本当に細かい単位で分割し、それらを組み合わせることで全体の機能を達成しようという試みになります。
サービスの分割単位は、一人が2週間で書き直せるレベルが推奨されてたりしますので、本当に細かい単位となります。
マイクロサービスのメリットは、サービス間のインターフェースさえ守っていれば、サービスの作りはその担当者ごとに自由にできる点です。例えばあるサービスはGo、あるサービスはNode.js、またあるサービスはC#、、、などということもできる点です。
また新しい技術を採用したい、となった場合にもサービス単位で採用することができるため、システム全体に対する影響が低いというメリットもあります。モノリシックではシステム全体に影響が出てしまうため、困難を極めることが多いでしょう。
その反面デメリットとしては、サービスを分割すること自体の難易度が高いことです。サービスを分割すると、今まで関数呼び出しでほとんどオーバーヘッドもなくお隣のモジュールを呼び出せていたのが、ネットワーク通信を挟んで非同期的に行われることとなります。この通信でのオーバーヘッドがバカにならないのと、非同期で通信することによる状態管理が難しくなってきたり、トランザクションどーすんのよ問題が出てきたりします。(これらの課題を解決するために「サービスの分割手法」「それを支える技術」があったりするわけですが、ここでは一旦割愛します)
他にもデプロイメントをどうするかという課題や、不具合が起こった時にどこのサービスが問題なのかが把握することが難しかったり、、、諸々と、本当に課題が山積みです。
そういった設計面での難易度の向上を受け入れてでも、上記のメリットを享受したい場合には有効な手段です。
モジュラーモノリス
これはモノリシックとマイクロサービスの中間となるのですが、サービスとしての分割はせず一つのサービスで提供する中で(つまりモノリシック)、サービス内部で綺麗にモジュール分割しようぜ、という考え方です。
メリットとしてはマイクロサービスよりもモジュールの分割が容易であることが挙げられます。マイクロサービスは分散システムなので、ネットワークを介した通信であることが前提となり、一度サービスを分割すると、「これちょっと分割ミスったな」と思ってもなかなか修正が困難だったりします。その点、モジュラーモノリスの場合はモノリスがベースなのでモジュール分割境界の修正も比較的容易となります。あとはモジュール化を適切に行うことで将来的なマイクロサービスへの移行が容易であると言われてたりします(ここに関する私の疑問点は後述)。
デメリットとしては、モノリスでも起きていたようなモジュール間で定められた規約を簡単に違反できる(参照してはいけない型やデータをいつの間にか参照していた、みたいな)ことが挙げられます。
あとは、個人的にですが、モジュラーモノリスのつもりで作っていたがいつの間にかモノリスになっていた、みたいなことになりやすかったりするのかな、と思っています。メリットとデメリットにあることがまさにその原因で、確固たる設計指針を立ててそれをメンバーが熟知していないと、一歩間違えばモノリスよりになってしまいます。
また、メリットにマイクロサービスへの移行が容易であると言われていると書きましたが、実際問題パフォーマンスやトランザクションの問題を考えると、マイクロサービスへの移行を見越したモジュール分割をせざるを得ないため、最終的に目指すべきモジュール分割を行うためにはマイクロサービス同等の設計考慮が必要となってしまう様な気がします。(分割境界の修正が比較的容易という点がある程度緩和してくれるとは思いますが。)
ミニサービス
これもモノリシックとマイクロサービスの中間の概念となりますが、モジュラーモノリスがモノリシック寄りだったのに対して、こちらはマイクロサービス寄りの考え方になります。
マイクロサービスはちょっと細かすぎだから、もっと大きな単位でサービス分割した方が楽なんじゃない?ということです。
マイクロサービスは機能単位でサービスを分割しますが、ミニサービスはドメイン単位での分割を行うことで、比較的大きな塊のサービスになります。
ミニサービスは最近(2018年ごろ?)出てきた考え方なので、あまり統一的な考え方もなさそうな雰囲気がありますが、やはりサービスを分割する上でマイクロサービスと同等の課題は出てくるはずです。ただドメイン単位の大きな塊で分割境界を決めることで、疎結合となるはずの境界を見つけやすくなる、みたいなイメージかと思います。
まとめ
まとめるとサービスの分割単位は以下の様な形になります。
今回はサーバーサイドWebアプリケーションアーキテクチャにおける、サービス分割の方針について調べてみました。
次回はサービスの分割手法について話してみたいと思います。
最後に
DWSではゴリゴリとエンジニアの採用を強化中なので、興味を持たれた方は以下のリンクより採用に関してご確認くださいませ!
https://mmmcorp.co.jp/recruit/