こんにちは。てぃろです。
今回は私が開発しているサーバーレスアプリのフレームワークを題材にサーバーレスアーキテクチャを解説します。
- そもそもサーバーレスアーキテクチャって何なのかわからない
- マネージドサービス同士がどう連携しているのかよくわかっていない
- 認証付きREST APIの動きについて知りたい
という方にオススメな内容になっています。
アーキテクチャを図解してマネージドサービス同士が実際どうつながっているのかをアクセスのユースケースごとに理解を進めていきます。
フレームワークの概要を知りたい方は以下の紹介記事をご覧ください。
これから解説に使うアプリは以下にデプロイしていますので、実際に触りながら理解を進めてもらえばよいかと思います。
https://vueslsapp.thiroyoshi.com/
サーバーレスアーキテクチャがどう繋がっているか理解する
![](https://thilog.com/wp-content/uploads/2021/01/network-1246209_1280-e1609811694633-1024x321.jpg)
サーバーレスアーキテクチャのアプリケーションは基本的にイベント駆動型で稼働するシステムであり、常にステートレスであることを意識する必要があります。
これを含めて理解していくためにも、まずはアーキテクチャの全体図からご覧ください。
![画像3](https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/22158483/picture_pc_97a956b6b268c542826884c8224e656b.jpg)
図の中の矢印は、どこからどこへどのようなリクエストがされているかを示しています。つまり、具体的にHTTPリクエストなどの電文が飛んでいる部分を表しています。
AWSの内部的に通信していると思われる部分も同様に矢印で示しているので、すべてがHTTPで通信しているかはわかりません。
ここで大事なのは”マネージドサービス同士が繋がることを理解する”ことであり、これは電文がどこからどこへ飛んでいるかを把握することに他なりません。
さらに深く理解するためには、イベント駆動であることから、電文がどのタイミングで飛ぶのかを把握することも必要です。
サンプルアプリでは、ユーザ操作のタイミングで電文が飛ぶと考えてOKです。その場合に考えられるユースケースは、以下の3つになります。
- ユーザが、Webサイトにアクセスする
- ユーザが、認証する
- ユーザが、Webサイトを操作する(APIコールする)
以下では、ユースケースごとに解説していきます。
ケース1:ユーザが、Webサイトにアクセスする
このケースはタイトルの通りですが、少し言い換えれば、ブラウザにアプリのURLを打ち込んで(URLをクリックして)HTTPリクエストを送った場合のケースと言えます。
図でいうと、以下の経路(赤線)です。
![画像3](https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/22158525/picture_pc_2aed869622af863e9c6cf946f8039c2e.jpg)
S3は静的ウェブサイトホスティングの設定をしてあるので、ファイルを配置するだけでWebサイトとして公開することができるようにしています。
配置しているファイルはVue.jsで開発しビルド済の静的ファイルのみです。
つまり、このアクセスではS3上の静的ファイルにアクセスし、ブラウザでページを描画し始めたところになります。
実は厳密には、Route 53で名前解決(エイリアスレコードの登録)もしてますが、簡単のため図には一旦表していません。
また、この図のままではWebサイトアクセスがHTTPのままなのですが、CloudFrontを追加してHTTPS化する追加ソースを用意しています。
追加の解説については後日公開します。
ケース2:ユーザが、認証する
ケース2はケース1のあとに起こるケースで、ユーザがログインするケースを示しています。
![画像4](https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/22158528/picture_pc_c72f530c3d470e14e501b26821c9a562.jpg)
図の経路(赤線)のように、ユーザのブラウザから直接Cognitoに認証要求を行います。Cognitoで認証ができれば、APIアクセスに必要な以下の情報が返ってきます。
- Access Token
- Refresh Token
- ID Token
これらの中でもID TokenはAPIアクセス時に認証情報として必要になる重要な情報です。
詳しい方はここでAPIアクセスに使うならAccess Token使うのが正解では?と思う方もいると思います。僕もそう思います。でも、このID Tokenを使うというのはCognitoの仕様のようで、Access Tokenは使えなかったのです。
以下の公式ドキュメントでもそのように説明されています。
Amazon Cognito ユーザープールと統合された REST API を呼び出す
なぜCognitoがこの仕様なのか詳しい経緯はわからないので、どなたか知ってる人がいたら教えてください…!
このID Tokenはログイン後はAPIアクセスするたびに利用する上、画面が更新されるなどしてもログイン中であれば保持しておきたいです。そこで、これらはブラウザのLocalStorageに保持させています。(SDKの仕様)
本アプリでは、正常にこれらの情報が返却されたあと、以下の条件でログイン中と判断します。
- LocalStorageにID Tokenが存在する
- ID Tokenの有効期限が切れていない
ちなみに、ID Tokenについてよく知りたい方は、以下の仕様書を読むことをオススメします。
OpenID Connect Core 1.0 incorporating errata set 1
いろいろなところに解説記事は転がっていますので、それで概要をつかむのは問題ないと思います。ですが、本当に自分がID Tokenを利用して実装するときには必ず読んで、この標準仕様に準拠しているかを確認するのが一番安全です。
ケース3:ユーザが、Webサイトを操作する(APIコールする)
最後のケースは、ログインしたあとにAPIをコールするケースです。
基本的にAPIコールで情報の参照と登録をしていますので、ここが一番重要なケースです。
![画像4](https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/22158538/picture_pc_6eca135d6290095a57ef6e5307bab6f4.jpg)
まず赤線の経路は、API Gatewayのエンドポイントの名前解決を意味しています。今回の実装ではカスタムドメインを設定しているので、その名前解決が必要、という意味です。
カスタムドメインを設定する一番の理由はデプロイのたびにエンドポイントを変えたくないからです。
本フレームワークはどこでもいつでも一回デプロイすれば使えるようにすることを目指しています。カスタムドメインを入れないとAPI Gatewayは毎回ランダムなエンドポイントを生成してしまいますので、フロントアプリでエンドポイントの設定し直すという手間が発生してしまうので、これを避けるためです。
次に、緑線の経路ですが、これがAPIコールそのものです。
まずHTTPSでアクセスしているので、HTTPSを復号する必要があります。カスタムドメインの設定で登録したドメインの証明書を使ってAPI Gatewayで復号してくれます。
このときの処理として、API Gatewayから伸びる下側の緑矢印でACM(Amazon Certificate Manager)へのアクセスを表現していますが、経路は厳密ではない可能性があります。ここではあくまで、ACMの証明書を使用していることを表現していると思ってください。
次に、API GatewayはCognitoに認証情報の確認をします。
これにはLambdaオーソライザー(旧カスタムオーソライザー)を使用しています。APIコールにはID Tokenが付加されているので、これを読み出してCognitoに認証済みのトークンで間違いないかをチェックしに行きます。API Gatewayから伸びる上側の緑矢印で表現しています。
認証のチェックが終わったら、API Gatewayから右側のLambdaが呼び出され、Lambda関数が実行されます。DynamoDBへのデータの読み書きはここで初めて行います。
Lambda関数の実行が完了したら、ユーザへAPIのレスポンスを返します。
まとめ
![](https://thilog.com/wp-content/uploads/2020/12/online-5059828_1280-e1609204438830-1024x320.jpg)
以上が、サーバーレスアーキテクチャで作ったWebアプリの解説です。
図だけ見ると登場するサービスが多くて混乱しそうになりますが、一つ一つをユースケースで見ると、実は単純なつながり方しかしてないというのがわかってもらえると思います。
まとめるとサーバーレスアーキテクチャには、次のようなメリットがあります。
- Lambda関数の処理を工夫するだけで、様々な処理を実現可能
- 複雑な処理をフロントで実装しなくていい(フロントはAPIを呼ぶだけ)
- 実装の影響は単一のLambdaに収まる
このようにサーバーレスアーキテクチャはこれまでのモノリシックアーキテクチャとは違う利点があります。
しかし、なんでもサーバーレスアーキテクチャにすればいいというものではありません。サーバーレスアーキテクチャは一つの開発方式として捉えて、有効な場面ではきっちり使えるようにしましょう。
ちなみに、AWSのアーキテクチャ図を描くためには以下のAWSから配布されているアイコン集を使うのがオススメです。
参考文献
- Amazon S3 での静的ウェブサイトのホスティング
- Amazon S3 バケットでホストされているウェブサイトへのトラフィックのルーティング
- REST API のカスタムドメイン名を設定する
- API Gateway Lambda オーソライザーの使用