このチュートリアルでは、複数のマイクロサービスのストレージ バックエンドとして Azure Database for PostgreSQL を使用します。 このチュートリアルでは、このようなクラスターのセットアップと基本的な操作のサンプルを示します。 具体的には、次の方法を学習します。
- [前提条件]
- マイクロサービスのロールを作成する
- psql ユーティリティを使用してロールと分散スキーマを作成する
- サンプル データ用のテーブルを作成する
- サービスを構成する
- サービスを実行する
- データベースを調べる
[前提条件]
次のいずれかの方法でエラスティック クラスターを作成します。
マイクロサービスのロールを作成する
エラスティック クラスター内に分散スキーマを動的に配置できます。 システムは、使用可能なノード全体にわたってそれらをユニット全体として再調整できるため、手動で割り当てなくてもクラスター リソース全体の効率が向上します。
マイクロサービス設計パターンにスキーマ シャーディングを適用する場合は、対応するマイクロサービスごとにデータベース スキーマを作成します。 また、データベースに接続するときは、マイクロサービスごとに個別の ROLE を使用します。 各ユーザーが接続すると、ロール名はsearch_pathの先頭に表示されます。 ロール名がスキーマ名と一致する場合、適切なsearch_pathを設定するためにアプリケーションを追加で変更する必要はありません。
この例では、次の 3 つのマイクロサービスを使用します。
- ユーザー
- time
- ping
各サービスのデータベース ロールを作成します。
CREATE USER user_service;
CREATE USER time_service;
CREATE USER ping_service;
psql ユーティリティを使用して分散スキーマを作成する
psql を使用してエラスティック クラスターに接続した後、いくつかの基本的なタスクを完了できます。
スキーマは、次の 2 つの方法で配布できます。
-
citus_schema_distribute(schema_name)関数を呼び出して手動で次の操作を行います。
CREATE SCHEMA AUTHORIZATION user_service;
CREATE SCHEMA AUTHORIZATION time_service;
CREATE SCHEMA AUTHORIZATION ping_service;
SELECT citus_schema_distribute('user_service');
SELECT citus_schema_distribute('time_service');
SELECT citus_schema_distribute('ping_service');
このメソッドを使用すると、既存の標準スキーマを分散スキーマに変換することもできます。
注
分散テーブルと参照テーブルを含まないスキーマのみを配布できます。
-
citus.enable_schema_based_sharding構成変数を有効にします。 現在のセッションの変数を変更することも、コーディネーター ノードのパラメーターから永続的に変更することもできます。 パラメーターを ON に設定すると、作成されたすべてのスキーマが既定で配布されます。
SET citus.enable_schema_based_sharding TO ON;
CREATE SCHEMA AUTHORIZATION user_service;
CREATE SCHEMA AUTHORIZATION time_service;
CREATE SCHEMA AUTHORIZATION ping_service;
次のコマンドを実行して、現在分散されているスキーマを一覧表示します。
SELECT * FROM citus_schemas;
schema_name | colocation_id | schema_size | schema_owner
-------------+---------------+-------------+--------------
user_service | 5 | 0 bytes | user_service
time_service | 6 | 0 bytes | time_service
ping_service | 7 | 0 bytes | ping_service
(3 rows)
サンプル データ用のテーブルを作成する
これで、すべてのマイクロサービスのエラスティック クラスターに接続できるようになりました。 次の例では、エラスティック クラスター データベースの名前は Citus です。 psql セッションから、\c コマンドを使用して別のユーザーにスワップできます。
\c citus user_service
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL
);
\c citus time_service
CREATE TABLE query_details (
id SERIAL PRIMARY KEY,
ip_address INET NOT NULL,
query_time TIMESTAMP NOT NULL
);
\c citus ping_service
CREATE TABLE ping_results (
id SERIAL PRIMARY KEY,
host VARCHAR(255) NOT NULL,
result TEXT NOT NULL
);
サービスを構成する
このチュートリアルでは、一連の単純なサービスを使用します。 これらは、次のパブリック リポジトリを複製することで取得できます。
git clone https://github.com/citusdata/citus-example-microservices.git
$ tree
.
├── LICENSE
├── README.md
├── ping
│ ├── app.py
│ ├── ping.sql
│ └── requirements.txt
├── time
│ ├── app.py
│ ├── requirements.txt
│ └── time.sql
└── user
├── app.py
├── requirements.txt
└── user.sql
ただし、サービスを実行する前に、エラスティック クラスターのuser/app.pyを提供するping/app.py、time/app.py、およびファイルを編集します。
# Database configuration
db_config = {
'host': 'EXAMPLE.postgres.database.azure.com',
'database': 'postgres',
'password': 'SECRET',
'user': 'ping_service',
'port': 5432
}
変更を行った後、変更したすべてのファイルを保存し、サービスを実行する次の手順に進みます。
サービスを実行する
すべてのアプリ ディレクトリに移動し、独自の Python 環境で実行します。
cd user
pipenv install
pipenv shell
python app.py
時刻サービスと ping サービスに対してコマンドを繰り返します。その後、API を使用できます。
一部のユーザーを作成します。
curl -X POST -H "Content-Type: application/json" -d '[
{"name": "John Doe", "email": "john@example.com"},
{"name": "Jane Smith", "email": "jane@example.com"},
{"name": "Mike Johnson", "email": "mike@example.com"},
{"name": "Emily Davis", "email": "emily@example.com"},
{"name": "David Wilson", "email": "david@example.com"},
{"name": "Sarah Thompson", "email": "sarah@example.com"},
{"name": "Alex Miller", "email": "alex@example.com"},
{"name": "Olivia Anderson", "email": "olivia@example.com"},
{"name": "Daniel Martin", "email": "daniel@example.com"},
{"name": "Sophia White", "email": "sophia@example.com"}
]' http://localhost:5000/users
作成されたユーザーを一覧表示します。
curl http://localhost:5000/users
現在の時刻を取得します。
Get current time:
example.com に対して ping を実行します。
curl -X POST -H "Content-Type: application/json" -d '{"host": "example.com"}' http://localhost:5002/ping
データベースを調べる
いくつかの API 関数を呼び出したので、データは保存され、citus_schemas に期待される内容が反映されているかどうかを確認できます。
SELECT * FROM citus_schemas;
schema_name | colocation_id | schema_size | schema_owner
-------------+---------------+-------------+--------------
user_service | 1 | 112 kB | user_service
time_service | 2 | 32 kB | time_service
ping_service | 3 | 32 kB | ping_service
(3 rows)
スキーマを作成したとき、スキーマを作成するマシンを指定しませんでした。 これは自動的に行われました。 次のクエリを使用すると、各スキーマが存在する場所を確認できます。
SELECT nodename,nodeport, table_name, pg_size_pretty(sum(shard_size))
FROM citus_shards
GROUP BY nodename,nodeport, table_name;
nodename | nodeport | table_name | pg_size_pretty
-----------+----------+---------------------------+----------------
localhost | 7001 | time_service.query_details | 32 kB
localhost | 7002 | user_service.users | 112 kB
localhost | 7002 | ping_service.ping_results | 32 kB
このページの出力例を簡潔にするため、nodename を IP アドレスとして使用する代わりに、localhost に置き換えています。
localhost:7001 がノード 1 で、localhost:7002 がノード 2 であるとします。
ユーザーと ping サービスが 2 番目の ノード localhost:7001 上のスペースを共有している間に、時刻サービスがノード localhost:7002 に配置されたことが確認できます。 サンプル アプリは単純で、ここでのデータ サイズは重要ではありませんが、ノード間の不均等なストレージ領域の使用率の影響を受けるものとします。 2つの小規模な時間サービスとpingサービスを1つのノードに配置し、対して大規模なユーザーサービスは専用のノードに配置する方が理にかなっています。
クラスターはディスク サイズによって簡単に再調整できます。
SELECT citus_rebalance_start();
NOTICE: Scheduled 1 moves as job 1
DETAIL: Rebalance scheduled as background job
HINT: To monitor progress, run: SELECT * FROM citus_rebalance_status();
citus_rebalance_start
-----------------------
1
(1 row)
完了したら、新しいレイアウトの外観を確認できます。
SELECT nodename,nodeport, table_name, pg_size_pretty(sum(shard_size))
FROM citus_shards
GROUP BY nodename,nodeport, table_name;
nodename | nodeport | table_name | pg_size_pretty
-----------+----------+---------------------------+----------------
localhost | 7001 | time_service.query_details | 32 kB
localhost | 7001 | ping_service.ping_results | 32 kB
localhost | 7002 | user_service.users | 112 kB
(3 rows)
期待通り、スキーマは移動され、よりバランスの取れたクラスターになっています。 この操作は、アプリケーションにとって透過的です。 再起動する必要さえなく、クエリの提供を続けます。