😺

大学システムのアーキテクチャを見直した話

に公開

はじめに

現在、私たちクロステックマネジメント(京都芸術大学)では、サービス利用者1,000万人規模を見据えた「学修・学務プロセスを支えるシステム」の開発に取り組んでいます。

ここでいう学修・学務プロセスとは、学生の履修、授業、課題、成績、各種手続きなど、大学における学びと運営を支える一連の業務プロセスを指します。

その中で私は、現在、システムの基盤設計を担うチームの一員として、「多くのユーザーに継続的かつ安定的に利用される仕組みを、どのように実現するか」を日々検討しています。

本記事では、そうした前提のもと、システムアーキテクチャとして当初検討していたマイクロサービスアーキテクチャを見直し、モジュラーモノリスアーキテクチャを採用するに至った経緯を記載していきます。

マイクロサービスアーキテクチャ採用の経緯

「マイクロサービスアーキテクチャ」と聞くと、どのようなイメージを持つでしょうか。

  • 各サービスが独立していて、チームごとにスピード感を持って開発できる。
  • 必要な部分だけを個別にスケールできる。
  • 変更の影響範囲を小さくできる。
  • そして何より、どこかモダンで、技術的にもかっこいい。

世間的に見ても、マイクロサービスは多くの組織で採用されているアーキテクチャです。

実際、O'Reillyがソフトウェアエンジニア、アーキテクト、意思決定者など1,502人を対象に実施した「2020年のマイクロサービス導入状況」の調査では、77%の組織がマイクロサービスを導入しており、そのうち92%が成功を感じているとされています。

さらに同調査では、チームが「作って終わり」ではなく、テスト、デプロイ、その後の保守まで責任を持つ場合、そうでないチームよりもマイクロサービスで成功する割合が18%高いとされています。

こうしたデータを見ると、マイクロサービスは多くの現場で成果を出しているアーキテクチャだと感じます。

また、私たちの組織も、もともと開発と運用を分けるのではなく、DevOps(開発から運用までを一貫して担う体制)を前提とした組織運営をしていました。

各チームが自分たちの領域を開発し、その後の改善や運用にも関わる体制だったため、マイクロサービスとの相性はよさそうに見えました。

さらに、当時検討していたシステムの構成とも、マイクロサービスの考え方は噛み合っているように見えました。

私たちが扱っていた大学向けのシステムには、大きく2種類のルールがありました。

  1. 法令や制度に紐づいた、大学側で自由に変えることのできないルール
  2. 大学ごとの方針や業務フローによって異なる運用ルール

前者は、法令や制度に紐づいているため、大学ごとの判断で自由に変更できるものではありません。
一方で後者は、大学ごとに業務の進め方や判断基準が異なる(たとえば、通学制の大学とオンライン大学では、授業運営・出席確認・課題提出・学生対応の進め方が異なる)ため、変化しやすく、個別性の高い領域です。

そこで私たちは、まずこの2つを性質の異なる領域として分けて考えました。そのうえで、大学ごとに異なる運用ルールについては、さらに業務ごとのサブシステムに分割することで、チームごとの担当範囲を明確にしやすくなると考えました。

各チームが自分たちの担当領域に集中できるようになれば、開発や意思決定も進めやすくなります。

このような考えから、当初はシステム全体の構成として、マイクロサービスアーキテクチャを採用することになりました。

マイクロサービスアーキテクチャの大変さを痛感

何が大変だったか。

サービス境界をどう分けるかが難しい

マイクロサービスでは、各サービスを独立して開発・変更しやすくするために、サービスごとの責任範囲を適切に分ける必要があります。

この境界設計の重要性は、世間的にも強く認識されています。

ドイツの専門職71人を対象としたマイクロサービス採用に関する調査では、回答者の79%が、サービス設計においてトランザクション境界を考慮することを「重要」または「非常に重要」と回答しています。

ここでいうトランザクション境界とは、「どこまでを一連の処理として扱うのか」「どこでデータの整合性を保つのか」という境界のことです。

境界の切り方が曖昧なままサービスを分割してしまうと、1つの機能を実現するために複数のサービスをまたぐ必要が出てきます。

その結果、サービス間通信が増え、依存関係も複雑になります。
さらに、1つの変更を行うだけでも複数チームとの調整が必要になり、サービス単位で独立して開発・変更・リリースすることが難しくなります。

マイクロサービスは、各サービスが独立して開発・運用できることに価値があります。にもかかわらず、サービス間の依存が強くなってしまうと、物理的には分かれていても、実態としては密結合なシステムになってしまいます。

そのため、境界が曖昧なまま分割してしまうと、マイクロサービスとして分けたメリットを十分に活かせない状態になってしまいます。

私たちのプロジェクトでも、立ち上げ期ということもあり、業務要件やシステム全体の構成がまだ固まりきっていない部分がありました。

そのため、「この機能はどのサービスが持つべきなのか」「このデータはどの領域の責任なのか」といった判断が難しい場面がありました。

たとえば、「学生のIDを誰が管理するか」が曖昧でした。

教務サービスは履修や成績を扱うために学生のIDを発行します。一方で、認可サービスも「この人は学生か?」を判定するために、同じIDを持つ必要があります。

本来、こうした「人」のデータは1つのサービスが正本として管理し、他のサービスはそれを参照するだけにすべきでした。しかし、誰が責任を持つかを決めずに進めた結果、両方のサービスが同じIDを別々に持つ構成になり、学生を1人増やすたびに、両者の間で同期を取る必要が出てきました。

「IDを管理する」という一見小さな責任でも、その境界を曖昧にしたまま分けてしまうと、本来1か所で完結するはずの変更が、複数のサービスをまたぐ調整に変わっていきます。

「独立して開発しやすくするために分けたはずなのに、分けたことで逆に依存や調整が増える」

これが、マイクロサービスアーキテクチャの難しさとして最初に強く感じた点でした。

モジュラーモノリスに移行した理由

ここまでの検討を通して、現時点ではマイクロサービスとしてサービスを物理的に分離するよりも、まずはモジュラーモノリスとして責任境界を整理する方が現実的だと考えるようになりました。

モジュラーモノリスは、1つのアプリケーションとして動かしながらも、内部では機能や業務領域ごとにモジュールを分ける構成です。

つまり、マイクロサービスのように最初からサービスを物理的に分離するのではなく、まずはアプリケーション内部で責任範囲を明確にしていく考え方です。

ここで重要なのは、マイクロサービスとモジュラーモノリスのどちらが優れているかではなく、今のプロジェクトのフェーズにどちらが合っているかでした。

マイクロサービスが力を発揮するのは、たとえば特定の機能だけに負荷が集中し、その部分だけを個別にスケールさせたい場合や、ドメインごとの責任境界が明確になり、独立したサービスとして切り出すメリットが十分に見えてきた場合だと考えています。

一方で、私たちはまだ業務要件やドメイン境界を整理している段階でした。この状態で最初からサービスを分割してしまうと、境界の見直しやサービス間連携の調整が増え、かえって開発の複雑さを高めてしまう可能性があります。

そのため、まずはモジュラーモノリスとして全体を見通しやすい構成を保ちながら、内部の責任境界を育てていく方が現実的だと判断しました。

将来の分割を見据えたモジュラーモノリス戦略

私たちが取った方針は、最初からサービスやDBを物理的に分けるのではなく、まずは1つのアプリケーションの中で責任境界を明確にしていくことでした。

具体的には、1つのDBインスタンスの中でスキーマを分割し、モジュールごとに管理するデータの範囲を分ける方針にしました。

これにより、サービスやDBを最初から分離しなくても、データの責任範囲をある程度明確にできます。

また、領域をまたぐ処理が発生した場合でも、モジュラーモノリスであれば単一プロセス内でトランザクションを完結できます。

マイクロサービスでは、サービスをまたぐ処理において、サービス間通信やデータ整合性の設計が必要になります。

一方で、モジュラーモノリスであれば、内部のモジュール境界を保ちながらも、トランザクションは1つのアプリケーション内で扱えるため、分散トランザクションの複雑さを避けやすくなります。

ただし、単に1つの大きなモノリスとして作るつもりはありませんでした。

将来的にマイクロサービス化が必要になる可能性もあるため、内部の境界はできるだけ明確に保つ方針にしました。

そのために採用したのが、スキーマ分割とContractベースのモジュール間通信です。

各モジュールが直接お互いの内部実装に依存するのではなく、公開されたContractを通じて連携することで、モジュール間の依存を整理しやすくなります。

これにより、将来的に特定のモジュールをマイクロサービスとして切り出す必要が出た場合にも、分割コストを抑えやすくなります。

つまり、今回の方針転換は「マイクロサービスを諦めた」というより、今のフェーズでは物理的なサービス分割よりも、ドメイン境界を見極めることを優先した判断です。

まずはモジュラーモノリスとして責任境界を育て、将来的にスケーラビリティや独立性の観点で必要が出てきたときに、改めてマイクロサービス化を検討できる状態を目指しています。

今後の展望

今後は、モジュラーモノリスとして全体を見通しやすい構成を保ちながら、内部の責任境界をより明確にしていきたいと考えています。

特に、モジュールごとの責任範囲、スキーマ単位でのデータ所有、Contractを通じたモジュール間連携を整理し、各モジュールが不要に他領域へ依存しない構成を目指します。

また、今回の方針転換はマイクロサービスを否定するものではありません。

まずはモジュラーモノリスとしてシンプルに開発・運用できる状態を作り、将来的に必要が出てきた場合には、特定のモジュールをマイクロサービスとして切り出せる余地を残しておきたいと考えています。

アーキテクチャは一度決めたら終わりではなく、組織やプロダクトの成長に合わせて見直していくものです。

今後も、今のフェーズに合った現実的な構成を選びながら、システムを育てていきたいと思います。

参考

おわりに

クロステック・マネジメント社は、「教育×AI」で次世代の学びを創造するために生まれた芸術大学発のスタートアップです。

ご興味のある方は、ぜひお気軽にお問い合わせいただけると嬉しいです!

https://www.wantedly.com/companies/company_7297732

クロステックマネジメント(京都芸術大学)

Discussion