原文はこちら
繰り返し述べていますが、ソリューションを選ぶ前にアプリケーションそれぞれが抱える独特の要件を評価すべきであり、そのためこのブログシリーズで紹介する私の意見はあなたの組織の選択とは異なってくるかもしれないことに留意してくださいね。あなたが自問すべき重要な問いは以下でしょう:
- 私の仕事にとってマイクロサービスは適切なツールだろうか?
- マイクロサービスは私の問題をメンテナンス可能な方法で解決するだろうか?
- 我々はこのソリューションを実装するに十分な予算を持っているだろうか?
新しい考え方を導入するとき、後では解決しがたい問題を招き入れてしまうこともあるため、これらを自問してみることは重要です。
マイクロサービスパターン
コードに進む前にマイクロサービスでのデータ管理のいくつかのパターンを定義するところから始めましょう。マイクロサービスの場合の最もわかりやすいパターンは、共有データベースパターンとサービス毎のデータベース(あるいはスキーマ)パターンです。ここから紹介していきます。
共有データベース
モノリスでは、通常我々はデータを単一のリレーショナルデータベースに保持します。これによりJOINを使ったクエリを書いたり、ACIDトランザクションを使ってデータ一貫性を保証したりと、永続化とクエリにまつわる部分を簡単に済ますことができます。共有データベースのマイクロサービスパターンでは、複数のサービスが単一のデータベースを共有しており、それぞれがテーブルをJOINしながらクエリをしてデータを取得したり、トランザクションを使用して一貫性を保証できる信頼性のあるやり方でデータを更新したりします。このことにより、このパターンは新人開発者たちにも理解しやすいものになっていますが、一方でAPIが複雑になってくると課題も生まれてきます。カラムを追加したりデフォルト値を変更したりすると同じテーブルにアクセスしているサービスを壊してしまうかもしれないため、スキーマの変更は他のサービスの開発者たちと調整したうえで行わなければなりません。また、長時間に渡るトランザクションが共有テーブル上でロックを保持することにより、他のサービスをブロックしてしまうかもしれません。更に、このパターンでは全てのサービスがデータをトラディショナルなリレーショナルデータベースに保持する前提となっており、NoSQLやGraph DBでドキュメントを利用する可能性を排除してしまっています(ただし少し後に紹介するようなワークアラウンドはあります)。
サービス毎のデータベース(あるいはスキーマ)
サービス毎のデータベース(あるいはスキーマ)パターンは共有データベースパターンのいくつかの欠点に対処しています。サービスがそれぞれ自身のデータベースを持っており、これは要はデータベースがサービスの実装の一部であるということを意味しています。このやり方ではスキーマの変更は他のサービスには影響しないということになります。なお、サービスごとにデータベース・サーバーを持つ必要は必ずしもありません。多くの場合サービスごとに独立したテーブル(他のサービスからはアクセスを制限されたユーザー、パーミッションをそれぞれのテーブルに付与しておきます)というかたち、あるいはサービスごとにユニークなスキーマを割り振るというかたちで実現されます。サービス毎のデータベースを利用するということはすなわち、サービスそれぞれの必要に応じて最も適した種類のデータベースを使えるようになるということを意味します。もちろん、このパターンにはデメリットもあります。トランザクションの管理が難しくなります。参照整合性の保証は簡単ではなくなるでしょう。データをJOINしてのクエリは不可能ではないにしても難しいでしょう。
もうわかったからコード見せてよ!
ここまでこのシリーズではマイクロサービスとは何か、あなたはなぜそれを使うべきなのかもしれないのかについて長々と語ってきましたが、理論を理解するのに最良な方法はいつもコードを見ることですよね。ということでようやくコードを見ていくことにします。このシリーズでは、何回かに分けてソーシャルメディア形式のアプリケーションのためのAPIを作っていきます。この中ではクラウドの様々な機能を使うだけでなく、いくつかの異なったマイクロサービスパターンを活用でき、そこに付き物となる興味深い問題への対処方法を紹介していくことになります。
ユーザーサービスの構築
説明
このサービスではHelidon MPをHibernateとともに利用し、ユーザーをOracle ATPインスタンスの
user
テーブルに永続化します。始めるために、Helidon Mavenアーキタイプを使いサービスのためにいくつかのファイルと構成の土台を作っていきましょう。以下がコマンドです(お好みに応じてパスを修正してもいいし、そのまま使ってもいいです):生成されたコードを見たり直したりする前に、このマイクロサービス用のスキーマユーザーを作成しておきましょう。可動しているATPインスタンスにadminユーザーとして接続し、次のクエリを実行する必要があります。このポストシリーズで紹介されているSQL Developer Webを使うと簡単にできます。準備ができたら、以下を実行してください(パスワードを強いものに修正するのをお忘れなく)。
SQL Developer Webを使っているなら、adminユーザーで以下のコマンドを使い各スキーマが有効化されていることを確かめておく必要があります:
上記のコマンドでは、プレースホルダの値は以下のように置き換えてください:
SCHEMA-NAME
はデータベーススキーマ名、全て大文字schema-alias
はスキーマ名のエイリアスで、SQL Developer Webを使ってアクセスする際にURLに使われます。Oracleはスキーマ名を暴露しないほうがよいというセキュリティ上の理由から、スキーマ名をそのまま使わないことを推奨しています。
ユーザーアクセスを有効化したら、ADMINユーザーから当該ユーザーにSQL Developer WebにアクセスするためのURLを提供しましょう。このURLはADMINユーザーがSQL Developer WebにアクセスするためのURLと同じものですが、ただし
admin/
の部分はschema-alias/
で置き換えてください。これ以降、私達は
usersvc
ユーザーを使っていくので、一旦SQL Developer Web(その他のツールをお使いならそのツール)からログアウトして先程作成した新しいユーザー名とパスワード、および上記で説明した適切なURLでログインし直しましょう。 usersvc
でログインしたら、以下を実行してマイクロサービス用のテーブルを作成します:次に、依存モジュールを取得しておく必要があります。プロジェクトルートに
/build-resource
というフォルダを作成し、更にその配下に /libs
というサブディレクトリを作成してください。ATPインスタンスと接続するために必要となるOJDBCドライバーをプロジェクトで使えるように、以下のJARファイルを取得する必要があります:- ojdbc8.jar
- oraclepki.jar
- osdt_cert.jar
- osdt_core.jar
Download the JARs from Oracle and place them in
OracleからJARをダウンロードし、
/build-resource/libs
. We also need to publish these to our local Maven repo so that when we run the application locally they'll be properly resolved. The following commands should help you out with that:OracleからJARをダウンロードし、
/build-resource/libs
に置きましょう。また、ローカルのMavenリポジトリにこれらをパブリッシュしておき、ローカルでアプリケーションを稼働させたときにこれらが適切にリゾルブされるようにしておきましょう。以下のコマンドでできます:次にpom.xmlファイルを修正し、JPAに必要な依存ライブラリであるHibernate、JacksonおよびOJDBCのJARを含むようにしておきます。次のエントリをdependenciesセクションに追加してください:
そしてHibernateの永続化に係る設定を追加する必要があります。
/src/main/resources/META-INF
に persistence.xml
という名前で以下のようにファイルを作成してください:そのディレクトリに行ってから、
microprofile-config.properties
を以下のように修正します:これで事前に必要な設定は全て終えたので、アプリケーションコードに進めます。生成された
GreetApplication.java
を探してください。それを修正してもいいですし、削除して新しく作るのでもいいんですが、結局の所以下のコードを含む UserApplication.java
が必要になります:Use the same process (modify or replace) for
同様に
GreetingProvider
to end up with a UserProvider
that looks like so:同様に
GreetingProvider
についても修正または削除して再作成して以下のUserProvider
を作ります:ここで
UserProvider
クラスはアプリケーション稼働時には生成された設定値を格納します。ここまででマイクロサービスの実ロジックを書き始める準備ができました。このシリーズの次のポストでは、コードを深く掘り下げていき、サービスをOracle Cloud上にデプロイ、稼働させてみます。