Top View


Author Yuhei Okazaki

Ruby on JetsとAurora Serverlessでスケールアウト可能なアプリケーションを構築する

2019/11/05

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 無しでの外部通信を皆さん熱望しているようですね。

Yuhei Okazaki

Yuhei Okazaki

Twitter X

2018年の年明けに組込み畑からやってきた、2児の父 兼 Webエンジニアです。 mockmockの開発・運用を担当しており、組込みエンジニア時代の経験を活かしてデバイスをプログラミングしたり、簡易的なIoTシステムを作ったりしています。主な開発言語はRuby、時々Go。