sam
lambda
serverless
ServerlessFramework
nuxt.js

GoとNuxt.jsでServerlessアプリケーションを構築する(AWS SAM+Serverless Framework)

年末年始を使ってServerlessアプリケーションを作りました。
「先月なにしてたっけ・・・?」という残念な人(自分)のために作った日記サービスです。
https://pastory.me

ちなみにLambdaにおけるコールドスタート対策は現在行なっていないので、サーバーの応答に数秒かかる時があると思います。

ソースコードはGitHubに置いています。

GitHub - hareku/pastory-web
GitHub - hareku/pastory-api

用いた技術は以下です。

  • Nuxt.js(フロント)
    • Serverless Framework
    • Lambda + API Gateway + S3 + CloudFront
  • Golang(バックエンド)
    • AWS SAM
    • Lambda + API Gateway
    • DynamoDB
    • Firebase Authentication

Serverlessアプリケーションを開発しての感想をまとめていきます。

「Serverless Framework」vs「AWS SAM」

両者ともServerlessアプリケーションのための開発/デプロイツールです。

今回はフロントであるNuxt.jsはServerless Frameworkを使い、バックエンドのGolangはSAM(Serverless Application Model)を使っています。それぞれの特徴と感想を述べておきます。

Serverless Frameworkの特徴

https://github.com/serverless/serverless/

  • 開発期間が長く、機能もSAMより豊富で安定している
  • 英語で検索すれば大体のことは出てくる(そして解決できる)
  • ローカルサーバーの起動はNode.jsしかできない(serverless-offlineというnpmパッケージ)

Node.jsのServerless開発ならこのServerless Framework一択です。プラグインが豊富にあり、S3への静的ファイル自動アップロード(serverless-s3-sync)や、Lambdaのコールドスタート対策(serverless-plugin-warmup)も簡単に導入できます。

ただ一方でNode.js以外だとローカル開発ができず、もししようとしても、リクエストを受け付けるコード部分を本番と開発で切り替える必要があります。そういったローカル開発という点では後述するAWS SAMが優れています。

AWS SAM(Serverless Application Model)

https://github.com/awslabs/serverless-application-model/

  • AWSが公式で提供しているため安定して運用できる
  • Goを含めたほとんどの言語でローカルサーバーを起動できる
  • Serverless Frameworkの後発のため機能が所々足りない

AWS SAMを使えばほとんどの言語でローカルサーバーを起動できます。しかし一つのHTTPリクエストで毎回Dockerのイメージを立ち上げて処理するため、レスポンスが最低でも2~3秒かかります。お世辞にもDeveloper Experienseが良いとは言えません。

そしてGolangなどの場合は予めファイルをビルドしておかなければならないため、Goファイルを編集する度にビルドしなければならないという手間もあります。またWindowsでデプロイするとLambdaでPermissionエラーが出る点も対応されていません。自分で別途aws/aws-lambda-goをリリースフローに組み込む必要があります。自分はおとなしくMacBookからデプロイしました。
awslabs/aws-sam-cli自体まだベータ版であるため、細かい改善点がまだまだ多いです。メジャー版でどれだけ改善されるかが期待されます。

認証はFirebase Authentication

独自の認証基盤を作る場合、多くは車輪の再発明になります。Firebase Authを利用するか、もしくはフレームワークに用意されているサードパーティパッケージを利用しましょう。
Nuxt.jsとGoを使ったFirebase Authの導入はこちらの記事が参考になります。
「Vue.js + Go言語 + Firebase 」で始める! Frontend Backend API 両方で認証するセキュアなSPA開発ハンズオン! - Qiita

データベースの選択

DynamoDB

AWSでのServerlessアプリケーションでは基本的にDynamoDBを使うことになります。DynamoDBはトランザクションにも対応しており、そして簡単にスケーリングできます。
しかしNoSQLであることは認識しなければなりません。DynamoDBではリレーションを用いてクエリを発行するなどは出来ず、MySQLでは3つのテーブルに対して1つのクエリですむ処理でも、DynamoDBでは少なくとも各テーブルごとに1クエリを発行する必要があります。アプリケーションの要件に合わせ、DynamoDBで対応できるか、そして今後対応していけそうかを考慮しておきましょう。

またDynamoDBは公式のDockerイメージが用意されており、ローカル開発に使用することができます。
https://hub.docker.com/r/amazon/dynamodb-local/

Aurora Serverless

Amazon Aurora ServerlessでHTTPSエンドポイントができ本当にサーバーレスアーキテクチャで利用可能になる! | DevelopersIO

最近Amazon Aurora ServerlessがHTTPを使って操作できるようになったみたいですが、まだまだServerlessアプリケーションに用いるべきでは無いと思います。
そもそもHTTPで使えて何が嬉しいかというと、VPC外からでもセキュアにAuroraを操作できるようになり、またLambdaにおけるコネクションプーリングの相性の悪さを解消できるという点です。ただ一方でAurora Serverlessはトランザクションに対応しておらず、今後対応するかも明言されていません。
また基本的にAurora Serverlessとのやり取りはJSONであるため、Aurora Serverlessに対応したORMを作るなどして対応する必要があります。その辺りで実装の手間が増えてしまう点は少し懸念点です。
Aurora Serverlessはあくまで「Aurora provided in serverless(Serverlessで提供されたAurora)」であり、「Aurora for serverless(serverlessのためのAurora)」ではないのです。

Firebase Realtime Database、Firestore

DynamoDBと比べて、Realtime Database(以下RTDB)やFirestoreが優れている点はリアルタイム同期ができることです。リアルタイム性を簡単に実現できるので、チャットアプリなどでも採用できます。

正直Firebaseはまともに触ったことがないで、RTDBやFirestoreについて詳しく述べることはできないです。ただ調べて見る限り、DynamoDBより扱えるデータ型が豊富だったり、無期限の無料枠でも十分に運用できたり、といった点が優れていると思われます。FirebaseがRTDBの次世代として使われていくみたいなので、またFirestoreを使って何か開発したいですね。

明確な理由を持ってServerlessに

今回初めてServerlessアプリケーションを本格的に作ってみました。
一言でまとめるなら「明確な理由が無いかぎりServerlessにするべきではない」という結論です。

今回の場合はサーバーコストを最小限にしたいという理由があり、そしてDynamoDBで十分に表現できるモデルという要件を満たしていました。
Serverlessだから開発コストを下げられるというのは、半分正解で、半分間違いです。扱う技術や要件によってはServerlessではない方が良いパターンもあります。

参考サイト

ひとこと

まだまだブラッシュアプすべき点はいくつもあります。
もしこのサービスを気に入ってくれたのならば、GitHubへのコントリビュートをお待ちしています。

https://pastory.me