1. はじめに
- これまでの記事「Amazon Aurora DSQL を使ってみる (1) 基本的な操作」、「Amazon Aurora DSQL を使ってみる (2) リージョン間同期の遅延確認」、「Amazon Aurora DSQL を使ってみる (3) 楽観的同時実行制御(OCC)の確認」にて、基本的な操作方法、リージョン間同期の遅延速度、楽観的同時実行制御の挙動について検証した。
- Aurora DSQLの気になるポイントとして、「システム全体をマルチリージョンで冗長化したい場合、結局どういう風に使えばいいのか?」がある。
- いろいろ設計のやり方があるのかもしれないが、今回はDynamodb Global Tableのような感じで、複数リージョンでAct/Actでの書き込み処理を行うような想定要件で、フロントのアプリっぽいものも含めて動作イメージを確認する。
2. やったこと
- Aurora DSQLをus-east-1/us-east-2のマルチリージョンで作成し、検証用のテーブルを作成する。
- us-east-1/us-east-2それぞれにEC2インスタンスにおいて、Flaskアプリ(メモ帳的なもの)からリージョン内のAurora DSQLエンドポイントに接続し、Webから入力されたコメントをAurora DSQLのテーブルに保存する。
- Flaskアプリを立てた、各リージョンのEC2インスタンスのEIPをRoute53のAレコードに登録する。通常時は50%/50%の加重ルーティングとし、ラウンドロビンで両方への読み書きができることを確認する。また、障害やメンテナンス時は加重ルーティングの値を変更し、片寄せができることを確認する。
3. 構成図
4. 手順
4.1 Aurora DSQL 検証用テーブル作成
- 以下の列を持つ検証用テーブルを作成する。
- comment: WEBから入力されたコメント
- time: コメントが入力された日付/時刻
- region: コメントが書き込まれたリージョン
create-table.sql
postgres=> CREATE TABLE comment_list (comment VARCHAR(50) NOT NULL, time TIMESTAMP NOT NULL, region VARCHAR(50) NOT NULL);
- テーブルは以下のようになる。
comment | time | region |
---|---|---|
hello | 2025-02-25 13:15:17 | us-east-1 |
bye | 2025-02-25 13:14:10 | us-east-1 |
thanks | 2025-02-25 13:10:10 | us-east-2 |
4.2 Flaskアプリ(メモ帳的なもの)の作成
必要資材のインストール
- Amazon Linux 2023に、以下の必要資材をインストールする。
- Flask: WEBサイト構築のため
- psycopg3: DSQL(PostgreSQL)への接続のため
- boto3: DSQLのパスワード(トークン)の取得のため
- FlaskからのSQL接続用に、Flask-SQLAlchemyを使いたかったが、DSQL接続時の必須設定となっている「sslmode=require」の対応方法がよく分からず今回は断念して、psycopg3でそのままSQL文を実行している。
[ec2-user@ip-10-0-0-65 ~]$ sudo dnf install pip
[ec2-user@ip-10-0-0-65 ~]$ pip install flask
[ec2-user@ip-10-0-0-65 ~]$ pip install "psycopg[binary]>=3”
[ec2-user@ip-10-0-0-65 ~]$ pip install boto3
WEBサイト構成ファイルの作成
- 以下の2つのファイルを作成する。
- myapp.py: メインロジック
- templates/memo-post.html: htmlのテンプレート
- おおまかな仕様としては以下。
- Flaskサーバにユーザが「http://x.x.x.x:5000/」でhttpアクセス(GET)すると、コメントの入力画面が表示される。ユーザがコメントを入力して送信ボタンを押すと、同じパスにhttpアクセス(POST)が行われる。
- FlaskサーバがPOSTリクエストを受けると、入力されたコメントを取得し、「コメント、処理した時刻、自分のリージョン」の3つをAurora DSQLのテーブルへINSERTする。INSERTした後、テーブルをSELECTして全レコードを取得し、memo-post.html(テンプレート)にレコードの内容を埋め込んでhtmlとして出力する。
- us-east-1のFlaskサーバを用いて書き込まれたコメントはus-east-1のAurora DSQLからus-east-2のAurora DSQLへ同期されるため、us-east-2側のFlaskサーバでもすぐに参照できる。
myapp.py
from flask import Flask, render_template, request
import psycopg
import boto3
from datetime import datetime
# DSQLのエンドポイントとリージョンは、自リージョンのものをそれぞれ指定
cluster_endpoint = "xxxxxxxxxxxxxxxxxxxxxxxx.dsql.us-east-1.on.aws"
region = 'us-east-1'
client = boto3.client("dsql", region_name=region)
password_token = client.generate_db_connect_admin_auth_token(cluster_endpoint, region)
conn = psycopg.connect(
dbname='postgres',
user='admin',
password=password_token,
host=cluster_endpoint,
sslmode='require'
)
conn.set_autocommit(True)
cur = conn.cursor()
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'GET':
cur.execute("SELECT * FROM comment_list ORDER BY time DESC")
results = cur.fetchall()
formatted_results = []
for row in results:
formatted_time = row[1].strftime('%Y-%m-%d %H:%M:%S')
formatted_results.append((row[0], formatted_time, row[2]))
return render_template('memo-post.html', comments=formatted_results)
if request.method == 'POST':
comment = request.form['data1']
itime = datetime.now()
cur.execute("INSERT INTO comment_list(comment, time, region) VALUES(%s, %s, %s)",(comment, itime, region))
cur.execute("SELECT * FROM comment_list ORDER BY time DESC")
results = cur.fetchall()
formatted_results = []
for row in results:
formatted_time = row[1].strftime('%Y-%m-%d %H:%M:%S')
formatted_results.append((row[0], formatted_time, row[2]))
return render_template('memo-post.html', comments=formatted_results)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
memo-post.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
</head>
<body>
<h1>DSQL マルチリージョンメモ帳 us-east-1</h1>
<form action="/" method="POST">
<input name="data1"></input>
<button type="submit">送信</button>
</form>
</body>
<h1>Comments</h1>
<ul>
{% for comment in comments %}
<li>{{ comment[0] }} - {{ comment[1] }} - {{ comment[2] }}</li>
{% endfor %}
</ul>
</html>
4.3 Route53レコード登録
- 所持しているパブリックドメイン(ここでは xxxxx.netとする)に、Aレコードを登録する。今回は以下のように登録する。
- 通常時は2つのFlaskサーバのIPアドレスが半々に返却される。加重の設定値を変更することで片寄せなどを行うことができる。
レコード名 | タイプ | ルーティングポリシー | 差別化要因 | 値 |
---|---|---|---|---|
memo | A | 加重 | 50 | xx.xx.xx.242 (us-east-1のインスタンス) |
memo | A | 加重 | 50 | yy.yy.yy.149 (us-east-2のインスタンス) |
4.4 Flaskアプリからの読み書きの確認
通常時の動作
- http://memo.xxxxx.net:5000 にアクセスすると、us-east-1/us-east-2のどちらかのFlaskサーバに半々の割合で接続される。(以下の画面はus-east-1側に接続した場合)
- コメント欄に「hello」と入力し送信すると、コメント、入力時刻、書き込んだリージョン、の3つの情報がINSERTされ保存され、その後SELECTした結果がComments欄に表示される。今回はus-east-1側で書き込まれていることが分かる。
- しばらくして同じURL(http://memo.xxxxx.net:5000)に再度アクセス(GET)すると、アクセス先がus-east-2側のFlaskサーバとなっている。GETアクセス時にSELECT文が実行されるが、先ほどus-east-1側でINSERTされた内容がus-east-2側に同期されてきているため、us-east-2側でもus-east-1側で登録したコメントが表示される。
- コメント欄に「bye」と入力し送信(POST)すると、コメント、入力時刻、書き込んだリージョン、の3つの情報がINSERTされ保存され、その後SELECTした結果がComments欄に表示される。レコードは両方のリージョン間で双方向同期されており、最初にus-east-1側で「hello」が、次にus-east-2側で「bye」が書き込まれたことが分かる。(Comments欄は新しいものを上に表示)
片系障害時の動作
- 片方のリージョンのFlaskサーバやAurora DSQLに障害が発生した場合、加重の値を変更して、トラフィックを片寄せする。今回は以下のように値を変更する。
レコード名 | タイプ | ルーティングポリシー | 差別化要因 | 値 |
---|---|---|---|---|
memo | A | 加重 | 0 | xx.xx.xx.242 (us-east-1のインスタンス) |
memo | A | 加重 | 100 | yy.yy.yy.149 (us-east-2のインスタンス) |
- レコードの設定変更反映後は、us-east-2側のIPアドレスのみが返却されるため、片寄せを行うことができる。
5. 所感
- しょぼいWEBアプリだが、一応アプリケーションも含めた使い方イメージが説明できるようになった。
- Aurora DSQLの接続では必須となっている「sslmode=require」の対応方法が分からず、SQLAlchemyのようなORマッパーを使うことができず、今回はSQLを直打ちしてしまった。今後やるときは改善したい。
6. 参考サイト/記事
- Flaskの基本的な使い方やDB接続の手順確認のため、主に以下のサイトを参考とさせて頂いた。