なぜサーバーレスアーキテクチャを選んだか(AWS Lambdaアプリケーション)

## 背景

自社新システムの開発のバックエンドを担当することになった際にサーバーレスアーキテクチャを選定したので、メリット・デメリットなどを合わせてなぜサーバーレスアーキテクチャにしたのか書きたいと思います。
## 前提

クラウドはAWSを利用しているのでAWS Lambdaを使用する前提です。
また、言語はRuby(2.5系)を使用しています。

## サーバーレス(AWS Lambda)のメリット・デメリット
### メリット

- インフラ構築の工数が削減できる
    - サーバーを管理する必要がないのでEC2インスタンスの構成などを考えること自体が不要です。(※VPCは設定できます)
    - アプリケーションエンジニアがシステムの大部分を管理できます。
- 自動スケーリング
    - 水平にスケーリングするため、パフォーマンスを維持できます。
    - メモリ圧迫により「サーバー落ち」が起きて再起動するまで利用できなくなるなどの心配がありません。
- 従量課金制
    - リクエストに比例して課金されるため、システムを使わない間は課金されません。
- 耐障害性
    - AWS Lambdaは各リージョンの複数のアベイラビリティーゾーンで管理されるため信頼性が高いです。

### デメリット

- サーバーレスの経験を持っている人材が比較的少ない印象のため、属人化する可能性があります。
- デフォルトだとエラーログがcloudwatch Logs頼みになってしまいます。
- クラウドベンダーに依存しやすいです。
    - AWSからGCPへの移行などがしづらい印象があります。

今回は利用するユーザが限定的かつ小規模な社内システムのため従量課金の方が金額的に妥当であり、
障害対応のリスクが少ない、AWS Lambdaを積極的に利用してきた、属人化はドキュメントを残すことで回避できる、などの理由からサーバーレス構成に決定しました。

## AWS Lambdaとは

FaaS(Function as a Service)の代表格とも言えます。

責務は「イベントに応じて関数を実行する」だけなのでサーバの管理が不要なのが特徴です。
サーバーレスと謳っていますが、あくまで管理不要というだけで裏ではコンテナが立ち上がっていて、そのコンテナ上で関数が実行されます。

API Gatewayをイベントトリガーに設定すればREST APIを構築したりできます。
関数単体でも使用できますし、アプリケーションとしても構築できます。

<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923148/292c32e4-a516-28fb-6d4d-512824fdd72c.png'>

### AWS Lambda × RDS

アンチパターンであったRDSとの組み合わせもRDS Proxyがリリースされたことで解消されました。

lambdaはリクエスト毎にコンテナを立ち上げるため、アプリケーションで直接RDSにコネクションを貼ってしまうと、例えば1000リクエスト同時に来たとすると1000コネクションを貼ることになります。

<img width='60%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923148/fa905874-9e36-f1a2-99b7-49110474d642.png'>

これだとDBのメモリがコネクション過多により不足してしまうので、RDSproxyを経由してコネクションをプーリングすることで大量アクセスによるDBのコネクション負荷を抑えることができます。

<img width='60%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923148/fa5a8921-566e-b083-a9d3-be2490238848.png'>

今回のシステムではこのRDS Proxyを使用しています。

## Ruby on Jets

AWS Lambdaによるアーキテクチャのメリットやデメリットが分かったので、次はアプリケーションのフレームワークを探してみました。

弊社ではRubyonRailsが馴染み深いため、「Railsライク」なフレームワークを探していたところ、RubyonJetsというフレームワークを見つけました。そこでgithubのスター数、最終更新日、トレンド性、ドキュメントの充実性を加味して決定しました。

[RubyonJets公式](https://rubyonjets.com/)
[Github](https://github.com/boltops-tools/jets)

## Ruby on Jetsの特徴

使ってみてわかったのが本当にRailsライクで、Railsを書いている感覚でアプリケーションが作成できます。
以下に特徴を挙げます。

- `routes.rb`に定義したもの→API Gatewayで定義
- controllerのアクション毎に関数が作成されます
- IAMロール、ポリシー、VPC、メモリ割当、タイムアウト時間、同時実行数などの設定をconfig/application.rbで管理できます
- ORMがActiveRecord
- ActiveSupportやActiveModelのメソッドを使用可能
- ローカルではjets serverコマンドでpumaを立ち上げて動作確認できます

また、嬉しかった点としてはstaging環境やその他のテスト環境を簡単に作成できることです。
環境を作成するというよりかは関数を複製するイメージに近いのでproductionとかなり近い環境を作成することができます。
具体的には`JETS_ENV`という環境変数をstagingやproductionに変えるだけで環境の作成と切り替えが可能です。

## まとめ

小規模なアプリケーションにAWS lambdaはとても有効だと思います。
フレームワークを探していてRuby on Railsに慣れているという方には、Ruby on Jetsがおすすめです。

Ruby on Jetsのdocker-composeでの環境構築からデプロイまでをまとめたのでリンクを貼っておきます。

- [docker-compose環境でRuby on Jetsの構築からデプロイまで<前編>](https://qiita.com/takashi-5/items/74b8ac4a342ae7372205)
- [docker-compose環境でRuby on Jetsの構築からデプロイまで<後編>](https://qiita.com/takashi-5/items/633e30027e8e8d2e1188)

## 参考
[サーバーレスの理解とメリット・デメリット（2020年版）](https://qiita.com/takanorig/items/3a3a0b43b5be5b4a124f)
[今なぜサーバーレスなのか](https://www.slideshare.net/YoshidaShingo/serverlessronten)
[Ruby on JetsとRDS Proxyを使ってRailsアプリをサーバレス化してみた](https://speakerdeck.com/yuuu/ruby-on-jetstords-proxywoshi-tuterailsapuriwosabaresuhua-sitemita)