Ruby on JetsとAurora Serverlessでスケールアウト可能なアプリケーションを構築する
2019/11/05
Table of Contents
Ruby on Jetsと組み合わせるデータベースをどうするか問題
Ruby on JetsはRDSまたはDynamoDBをデータベースとして使うことができます。しかし、どちらも一長一短です。
DynamoDBを使う場合
メリット
- スケールアウトできる
- 読み書きが速い
- アクセス制限しやすい
デメリット
- 使い慣れていない
- テーブル設計が難しい
- スケールアウトしたとき、料金が高額となる恐れがある
- インターネット経由もしくはVPCエンドポイント経由でしかアクセスできない
RDSを使う場合
一般的にRDSとLambdaは非常に相性が悪いと言われています。ただ、もちろんメリットもあります。
メリット
- これまで使い慣れている
- テーブルの結合や検索を簡単に実現できる
- LambdaをVPCに配置する場合、インターネットを経由せずにアクセスできる
デメリット
- Lambdaがスケールアウトしたとき、Lambda - RDS間のコネクションが増加し、コネクション枯渇が起こる可能性がある
- LambdaをVPCに配置する場合、起動に時間がかかる
- LambdaをVPCに配置する場合、インターネットと通信するためのNAT-Gatewayを設置する必要がある
RDSを使いたい
これまで運用してきたシステムをリプレースする場合や、インターネット経由でのDBアクセスが許可されないケース、複雑な検索を実現したい場合などどうしてもRDSを使いたいケースがあります。
従来はVPC内にLambdaを置くことに関して諸問題が多くありました。しかし、9月のアップデートによってそれらのほとんどが解決しています。
※Lambdaがインターネットを通信する際にNAT-Gatewayを設置する必要がある、という点のみ注意が必要です
そこで考えたのが、Aurora Serverlessを用いる方法です。Aurora Serverlessを使うことでRDSを使いながらスケールアウトが可能なサーバレスシステムを構築できないか、検証してみることにしました。
アーキテクチャ
ポイントは以下の通りです。
- LambdaをVPC内に配置する
- RDSはAurora Serverlessを選択する
- VPC内にNAT-Gatewayを配置する
構築
基本的な構築手順は以下にまとめています。今回はDBをAurora DBとする必要があるのでご注意ください。
上記手順を実施後、Jetsのドキュメントを参考に、LambdaをVPC内に設置するようにします。
LambdaをVPC内に配置する
Ruby on Jetsは設定一つでLambdaをVPC内に配置することができます。
config/environments/development.rb
へ以下のように追記します。
VPCやサブネットはAWSコンソールで予め作成しておく必要があります。
Jets.application.configure do
# Example:
# config.function.memory_size = 1536
# config.action_mailer.raise_delivery_errors = false
# Docs: http://rubyonjets.com/docs/email-sending/
config.function.vpc_config = {
security_group_ids: %w[sg-06ad7a7584385b79e],
subnet_ids: %w[subnet-042f4d57492386797]
}
end
サブネットのルーティングを修正
privateなサブネットにNAT-Gatewayを作成し、インターネットへのアクセスをNAT-Gatewayに向けます。
以上で準備完了です。
検証
heyというCLIツールを使って、システムへ一斉にリクエストを送信してみました。 RDSのときは82リクエストが限界だったので、100リクエストで試してみます。
$ hey -c 100 -n 100 https://ogzfa3ixle.execute-api.ap-northeast-1.amazonaws.com/dev/posts
Summary:
Total: 5.8760 secs
Slowest: 5.8747 secs
Fastest: 0.3161 secs
Average: 3.8788 secs
Requests/sec: 17.0184
Total data: 160300 bytes
Size/request: 1603 bytes
Response time histogram:
0.316 [1] |■
0.872 [0] |
1.428 [0] |
1.984 [0] |
2.540 [0] |
3.095 [4] |■■■
3.651 [49] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
4.207 [23] |■■■■■■■■■■■■■■■■■■■
4.763 [0] |
5.319 [20] |■■■■■■■■■■■■■■■■
5.875 [3] |■■
Latency distribution:
10% in 3.3001 secs
25% in 3.4143 secs
50% in 3.6105 secs
75% in 3.7445 secs
90% in 5.2640 secs
95% in 5.2968 secs
99% in 5.8747 secs
Details (average, fastest, slowest):
DNS+dialup: 0.2295 secs, 0.3161 secs, 5.8747 secs
DNS-lookup: 0.0297 secs, 0.0256 secs, 0.0327 secs
req write: 0.0001 secs, 0.0000 secs, 0.0007 secs
resp wait: 3.6490 secs, 0.1042 secs, 5.6394 secs
resp read: 0.0001 secs, 0.0001 secs, 0.0003 secs
Status code distribution:
[200] 100 responses
100リクエストすべて成功しています。
では200リクエストだとどうでしょうか?
$ hey -c 200 -n 200 https://ogzfa3ixle.execute-api.ap-northeast-1.amazonaws.com/dev/posts
Summary:
Total: 3.2330 secs
Slowest: 3.2105 secs
Fastest: 0.3245 secs
Average: 0.4907 secs
Requests/sec: 61.8617
Total data: 320600 bytes
Size/request: 1603 bytes
Response time histogram:
0.324 [1] |
0.613 [193] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
0.902 [0] |
1.190 [0] |
1.479 [0] |
1.767 [0] |
2.056 [0] |
2.345 [0] |
2.633 [0] |
2.922 [0] |
3.210 [6] |■
Latency distribution:
10% in 0.3418 secs
25% in 0.3559 secs
50% in 0.4218 secs
75% in 0.4511 secs
90% in 0.4772 secs
95% in 0.4842 secs
99% in 3.2091 secs
Details (average, fastest, slowest):
DNS+dialup: 0.1805 secs, 0.3245 secs, 3.2105 secs
DNS-lookup: 0.0313 secs, 0.0267 secs, 0.0381 secs
req write: 0.0002 secs, 0.0000 secs, 0.0019 secs
resp wait: 0.2159 secs, 0.0898 secs, 2.8738 secs
resp read: 0.0001 secs, 0.0000 secs, 0.0008 secs
Status code distribution:
[200] 200 responses
やはり成功しています。スケールアウトできているようですね。
まとめ
NAT-Gatewayを配置する必要はあるものの、スケールアウト可能なサーバレスアプリケーションを実現することができました。
もうすぐ re:Invent 2019が開催されるので、サーバレスに関して新たなリリースに期待したいと思います。
余談
この記事を書いている最中、タイムリーなスライドが公開されていました。
やはり NAT-Gateway 無しでの外部通信を皆さん熱望しているようですね。
Related Posts
kakudaisuke
2021/12/10
Yuhei Okazaki
2021/09/29