Lambdaで簡単なバックエンド作りたい。ただスロットリングくらいは欲しい
Slackアプリを作りたい、IoTのクラウド側を作りたい、といった、"ちょっとしたこと"なら、samを使ってAWS Lambdaでさらっとバックエンドを作りたいということがあるでしょう。
ただ、セキュリティ的な観点で、最低限の対応としてスロットリングくらいは欲しいです。
分かれば簡単です。やることは、AWS::Serverless::Api
にMethodSettings
を追加し、ThrottlingRateLimit
とThrottlingBurstLimit
を設定し、これをAWS::Serverless::Function
のRestApiId
に指定するだけです。
以下が実例です。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
NAME OF YOUR STACK
Globals:
Function:
Timeout: 3
Resources:
YourStackApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
MethodSettings:
- ResourcePath: /
HttpMethod: POST
ThrottlingRateLimit: 1
ThrottlingBurstLimit: 2
YourFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: your-function/
Handler: app.lambdaHandler
Runtime: nodejs14.x
Events:
HelloWorld:
Type: Api
Properties:
Path: /hogehoge
Method: post
RestApiId: !Ref YourStackApi
Outputs:
YourStackApiUrl:
Description: "API Gateway endpoint URL for Prod stage"
Value: !Sub "https://${YourStackApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hogehoge/"
YourFunctionArn:
Description: "Lambda Function ARN"
Value: !GetAtt YourFunction.Arn
許容可能な流量は、ThrottlingRateLimit
と、ThrottlingBurstLimit
で設定できます。
ThrottlingRateLimit
は、Lambdaに届くリクエストの流量をなだらかにする役割があります。上の設定だと、1秒間に2つのリクエストが同時に入ってきても、Lambdaには2秒後にその2つのリクエストが届きます。
ThrottlingBurstLimit
は、一気に大量のリクエストがAPI Gatewayに届いた場合に、一定のリクエストを破棄する機能になります。上の設定だと、1秒間に3つ以上のリクエストが同時に入ってきたら、429 Too Many Requestsがクライアントに返ります。
万が一のDDoSに備えてスロットリングを設定したい場合は、ThrottlingBurstLimit
を設定すればOKです。ThrottlingRateLimit
は必要に応じて利用します(上の設定のような小さい値の場合は、あまり意味がないです)。
トークンバケットアルゴリズム
少し2つの変数の意味を補足します。ただ、そのためには先に、API Gatewayが採用する、トークンバケットアルゴリズムに触れておきます。
トークンバケットアルゴリズムは流量制限のアルゴリズムです。トラヒックシェーピング、という入ってくるリクエストの量をできるだけ穏やかにしよう、バーストすぎて無理な場合は入れないようにしよう、という場合に利用されます。
イメージとしては、関所(API Gateway)があって、そこにリクエストという荷物が流れてきて、許可のあるものから関所を通過できる、という状況を想像してください。
トークンバケットアルゴリズムには、バケットとトークンという用語があります。
- バケット
- 入ってくるリクエストが一旦入る箱。このバケットを超えるリクエストがどっと押し寄せたら、溢れたものは捨てられる(429 Too Many Requestsがクライアントに返る)。つまり、一度に押し寄せても対処できるリクエスト量を意味する。
- トークン
- バケットに付けられるリクエストの通行手形。そのバケット内のリクエストを、バックエンドに流しても良いことを示す許可状のようなもの。バケットには複数のトークンをつけることが可能で、トークン一枚に付き、そのバケットの一定量のリクエスト(通常1件?)が通過できる。バケットには、一定時間ごとにトークンが追加される。バケット内のリクエストが通過したら、通過した分のリクエストと対応するトークンが、バケットから剥がされる。
バケットにこの一定時間ごとに付くトークンの枚数が、許容可能な送信レートであり、ThrottlingRateLimit
です。バケットのサイズが、ThrottlingBurstLimit
です。
Discussion