デジタル庁は業務システムのマイクロサービス化をずっと推奨している。
マイクロサービスは操作的定義では*1排他的なデータベース利用を行うWeb APIのことだ。他のサービスや(ブラウザーで動くJavaScriptを含む)アプリケーションから呼び出されて使われる。このようなWeb APIの集合体によるアプリケーションを指すこともある*2。
比較的新しい設計手法なので優れていると思われがちだが、大概のケースで上手くいかないアプローチだと知られている。
1. 見るからにダメなマイクロサービス化
旧来のモノリシック・アプリケーションの例として、ユーザー認証と売上管理と在庫管理の機能が一体化した小規模な構成のアプリケーションを考えよう。
マイクロサービス化すると、以下のようになる。
見るからにヤバイ。技術的にはひとつのDBMSに複数のデータベースを持てるし、ひとつの物理サーバーで仮想化を用いて多数のサービスを提供することもできるが、ややこしくなる事は変わらない。
データベース間の連携、とくにトランザクション処理が困難になる。更新処理中にエラーや例外が生じても、ロールバックは簡単に行えない。マイクロサービス化をするとシステムが複雑になるため、開発と運用が困難になり、パフォーマンスが悪く、データ整合性をとるのが苦労するのは、現在ではよく知られている話だ。マイクロサービス化を目指したが、現実的に無理だと気づいてやめたような体験談はいくつもある*3。
2. モノリシックだが疎結合なアプリケーション
モノリシック*4なサービスは単一のコードベースで一体化しているため、開発が進むとソフトウェアの拡張と保守が困難になるから、マイクロサービス化は複雑であっても有用という説明がされることがある。これも嘘だ。
モジュラーモノリスと呼ばれるが、複数の独立性の高いサービスで一つのアプリケーションを構成する事は難しくない。上の例を、以下のように構成することもできる。
ユーザー認証をSSOサーバー(IAM)に委託し、マスター管理を別アプリケーションにしている。
マスター管理と受注/在庫管理の間のデータ連携は、同じデータベースの同じテーブルを共有するので容易に行える。トランザクション処理も複雑な処理は要らない。
3. スキーマでビジネスロジックに一貫性を持たせる
ビジネスロジック(テーブルの更新ルール)を決めておく必要はある*5。リーダーシップと、他の開発チームに仕様(と仕様変更)を伝えるコミュニケーションが必要になる*6。ルールの運用を個々の開発者任せにすると、あるサービスに生じたバグが他のサービスの稼働に影響することもありえる。モノリシックなアプリケーションは些細な変更でも、アプリケーション全体のテストが必要云々と言われる理由だ。だが、これはデータベースのスキーマで解決出来る。
ORM世代は忘れがちなのだが、データベースのテーブルには複雑な制約をつけることもできるし、ユーザーロールを細かく設定することが可能だ。上の事例ではマスターデータのシェアしか行わないので、受注/在庫サービスにはマスターデータの変更権限を与えなければ済む。データベースでビジネスロジックを実装することも、その利用を強制することもできる。テーブルの直接操作を禁じ、ストアードプロシージャ/ファンクションを用意して、それを通してのみ更新を可能にすれば*7、データ操作のルールは徹底される。
ストアードプロシージャ/ファンクションを書くのは難しいと思っている人々もいるのだが、データベースの操作を制御文つきでまとめるだけなので、そんなことはない*8。(使ったことはないが)デバッガーもある*9。テスティングフレームワークもある*10。汎用的なプログラミング言語が使える場合もある。ユーザーロールの定義と組み合わせても、Web APIを用意する方がずっと手間暇がかかる。
4. まとめ
システム開発の独立性をあげるためのマイクロサービス化は大概は失敗となる。http(s)レイヤーでのリモートプロシージャコールはトランザクション処理ができないし、煩雑でオーバーヘッドが大きいし、実機でも仮想でもコンテナでも無闇にサーバーを増やすのは管理コストを引き上げる。
代替策もある。セキュリティーディファイナー設定のストアードプロシージャ/ファンクションは、多くのケースで上手くいくはずだ*11。何十年とある十分成熟したテクノロジーである。他にJavaのEJBによるリモートプロシージャコール(RPC)と言う方法もあり、一時期流行っていた。こちらはストアドほど手軽には扱えないが。
サービスの拡張性と保守性を担保したいのであれば、マイクロサービス化よりもデータベースのスキーマを見直すところからはじめよう。スケーラビリティが必要のないケースであれば、それで十分間に合うはずだ*12。少数となる従業員が利用する機能はモノシリックなサービスで、多数となる消費者向けの機能はマイクロサービスにしたと言う話があったが、適材適所が大事。
*1アプリケーションの一部分を成す小さなサービスで、独立にデプロイが可能で、http(s)に限らず通信を行うと説明されることが多いが、性質を考えるには抽象的すぎる。実用ではhttp(s)によるAPIの提供がほとんどである実態、サービスごとにデータベースを分けろと言うベストプラクティスから考えた方が良い。
*2マイクロサービス・アーキテクチャーと書き分ける方が適切。
*3サーバーの台数を見積もってやめたとか、仮想サーバーの数を〃、コンテナーの数を〃、Kubernetesの学習難易度を見てやめたと言うところもあるはずだ。
*4マイクロサービスの対義語としてモノシリックと言う言葉が選ばれているが、アプリケーションを複数のサービスに分割してはいけないと言う決まりはない。
*5複数のテーブルを同時更新する場合、ルールに沿わないと不整合データになって完全性が損なわれるし、ロックする順序を間違えるとデッドロックが生じる。
*6大きな会社の古いデータベースを見ると、出入りのソフトウェア開発会社の数だけ同じようなテーブルがあったりして、リーダーシップとコミュニケーションの欠如を感じることもある。
*7ストアドを呼び出すと、そのストアド作成者の権限でストアドが実行できるSECURITY DEFINERやAUTHID DEFINERといった設定をつけられる。PostgreSQLについたのは、約23年前のバージョン7.3であった。
*8使ったことがない技術は難易度が高く感じることが多いが、PostgreSQLの権限付与で、直接INSERTは禁止し、ストアド経由INSERTを許可する例を書いておいたので、ポチポチと簡単なことを確認して欲しい。
*9Oracle SQL DeveloperやPL/pgSQL用のpldebuggerがある。
*10Oracle PL/SQLにはutPLSQL、PostgreSQL PL/pgSQLにはpgTAPがある。
*11作成したストアドの仕様を共有する必要があるが、ドキュメント化の他、テストを兼任したサンプルコードを添えることを推奨しておきたい。テストコードは必ず書くもので追加の作業は少ない一方、ストアド利用者の仕様の理解が進むし、第三者がストアドを拡張するときに互換性を維持しやすくなる。
*12デジタル庁でクラウドを担当している人々は、スケーラビリティを重視しており、データの一貫性の維持は軽視している(関連記事:ギーク感あふれるデジタル庁クラウドチームのデータベースへの理解)。
*13社内SEがしっかりデータベースのER図をつくっている会社もあるが、書類はない、あっても現行アプリとあわない、DESCRIBEコマンドが便り〜と言う場合もある。2026年の今なら生成Aiに頼れたりするのかも知れないが、昨年まではつらかった。





0 コメント:
コメントを投稿