はじめに
最近のAPI開発ではLambdaを使って開発する機会が増えていると思います。Lambda開発では一般的にDynamoDBとの相性がよく採用されているケースが多いと思います。
DynamoDBを使うにあたって、テーブル内の1つの要素に対して大量のリクエストがあった場合に、ホットパーティションによるスロットリングの発生してしまう可能性があります。
今回はそのスロットリングの発生から解消までをAWSコンソール上から確認していきたいと思います。
内容
スロットリングとは
一定期間で受けられるリクエストの数を設定して、それを超えてきたら受信拒否してエラーを返却することです。
これはエンドポイントURLに対するリクエスト数が多すぎる場合、制限をかけることでトラフィックの急増に対しバックエンドサービスを守ってくれるそうです。これがDDoS攻撃などに対策になっていると思います。
AWSサービスではこういった制限をかけてくれていますが、作るシステムによっては頻繁にリソースへアクセスが予想されるものもあると思います。その場合は制限を回避するようにしなければいけません。
DynamoDBのスロットリング
プロジョンタイプで予想されるアクセス数に対応できるキャパシティユニットで設定しておけば急なアクセス増加にも対応しておくことはできるが、コストがかかってしまうので、現実的にオンデマンドで対応したいところです。
オンデマンドタイプでは、以下の場合にスロットリングが発生する可能性があるとawsのサイトに記載がありました。
・トラフィックが前のピークに比べて 2 倍以上である。
・トラフィックがパーティションごとの最大値を超えている。
・トラフィックがテーブルごとのアカウントクォータを超えています。
・テーブルのグローバルセカンダリインデックスがスロットルされている。
試したこと
urlをプライマリーキーにしたモックAPIのレスポンスをキャッシュするテーブルを作成し、当該テーブルの1項目に対して1分間あたり500回のgetリクエストを送る。
キー | 値 |
---|---|
url | PK |
response | モックAPIのレスポンス |
今回のエラー内容
software.amazon.awssdk.services.dynamodb.model.DynamoDbException: Throughput exceeds the current capacity of your table or index. DynamoDB is automatically scaling your table or index so please try again shortly. If exceptions persist, check if you have a hot key: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-partition-key-design.html (Service: DynamoDb, Status Code: 400, Request ID: 3PSHGOAO0277BFLPUE899O24PVVV4KQNSO5AEMVJF66Q9ASUAAJG)
CloudWatch Contributor Insights for DynamoDB
こちらのグラフでスロットリングが発生していることが確認できます。
回避方法
今回はURLというパーティションキーへのアクセスが集中してホットパーティションとなっていそうだったため、今回の事象は、
・トラフィックがパーティションごとの最大値を超えている。
と仮定して、書き込みシャーディングを使用してワークロードを均等に分散する方法を試してみました。
実際の作業内容は単純で、dynamo保存時にキーに1~100のサフィックスを付与し、同じ内容のものを100項目書き込む方法になります。
以下のような項目になります。
url | response |
---|---|
http://test.com?key=value-1 | {"response": "test"} |
http://test.com?key=value-2 | {"response": "test"} |
http://test.com?key=value-3 | {"response": "test"} |
... | ... |
http://test.com?key=value-100 | {"response": "test"} |
キャッシュ取得の検索時に、1~100のランダム数をサフィックスに付与することで読み込みが100個分分散されることになりました。
再度実行してみたところエラーはなくなり、正常に終了しておりました。
おわりに
ドキュメント上でDynamoDBの性能の良さは聞いていたが、大量データを扱っても高速に処理してくれることを実際に大量リクエストを送ってみて実感できました。
明日は @Nebel-hb さんの記事です。乞うご期待を!