⚙️

Lambdaで簡単なバックエンド作りたい。ただスロットリングくらいは欲しい

2022/12/20に公開

Slackアプリを作りたい、IoTのクラウド側を作りたい、といった、"ちょっとしたこと"なら、samを使ってAWS Lambdaでさらっとバックエンドを作りたいということがあるでしょう。

ただ、セキュリティ的な観点で、最低限の対応としてスロットリングくらいは欲しいです。

分かれば簡単です。やることは、AWS::Serverless::ApiMethodSettingsを追加し、ThrottlingRateLimitThrottlingBurstLimitを設定し、これをAWS::Serverless::FunctionRestApiIdに指定するだけです。

以下が実例です。

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