aws-serverless について
AWS サーバーレスアプリケーションを構築する開発者向けのパターンガイドです。Lambda ハンドラー、API Gateway 連携、再試行や DLQ を含む SQS 非同期処理を扱います。
主な機能
- 01Lambda ハンドラーの構成とエラー処理
- 02API Gateway 連携パターン
- 03SQS トリガーによる非同期処理
- 04バッチ失敗の報告と再試行
- 05デッドレターキューの設定
活用シーン
- 01Lambda API ハンドラーの実装
- 02Lambda による REST/HTTP エンドポイントの構築
- 03再試行と DLQ を使った SQS メッセージ処理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ davila7/ claude-code-templates --skill aws-serverlessインストール後、Claude Code で/aws-serverlessを入力して読み込まれたか確認します。
詳細
AWS Serverless
パターン
Lambda ハンドラーパターン
エラー処理を備えた適切な Lambda 関数の構造
使用する場面: ['Lambda 関数を実装するすべての場合', 'API ハンドラー、イベントプロセッサー、スケジュールタスク']
```javascript
// Node.js Lambda Handler
// handler.js
// Initialize outside handler (reused across invocations)
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
const { DynamoDBDocumentClient, GetCommand } = require('@aws-sdk/lib-dynamodb');
const client = new DynamoDBClient({});
const docClient = DynamoDBDocumentClient.from(client);
// Handler function
exports.handler = async (event, context) => {
// Optional: Don't wait for event loop to clear (Node.js)
context.callbackWaitsForEmptyEventLoop = false;
try {
// Parse input based on event source
const body = typeof event.body === 'string'
? JSON.parse(event.body)
: event.body;
// Business logic
const result = await processRequest(body);
// Return API Gateway compatible response
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify(result)
};
} catch (error) {
console.error('Error:', JSON.stringify({
error: error.message,
stack: error.stack,
requestId: context.awsRequestId
}));
return {
statusCode: error.statusCode || 500,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
error: error.message || 'Internal server error'
})
};
}
};
async function processRequest(data) {
// Your business logic here
const result = await docClient.send(new GetCommand({
TableName: process.env.TABLE_NAME,
Key: { id: data.id }
}));
return result.Item;
}
# Python Lambda Handler
# handler.py
import json
import os
import logging
import boto3
from botocore.exceptions import ClientError
# Initialize outside handler (reused across invocations)
logger = logging.getLogger()
logger.setLevel(logging.INFO)
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.environ['TABLE_NAME'])
def handler(event, context):
try:
# Parse i
API Gateway 統合パターン
Lambda と連携する REST API および HTTP API の統合
使用する場面: ['Lambda を基盤とする REST API を構築する場合', '関数に HTTP エンドポイントが必要な場合']
```yaml
# template.yaml (SAM)
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Runtime: nodejs20.x
Timeout: 30
MemorySize: 256
Environment:
Variables:
TABLE_NAME: !Ref ItemsTable
Resources:
# HTTP API (recommended for simple use cases)
HttpApi:
Type: AWS::Serverless::HttpApi
Properties:
StageName: prod
CorsConfiguration:
AllowOrigins:
- "*"
AllowMethods:
- GET
- POST
- DELETE
AllowHeaders:
- "*"
# Lambda Functions
GetItemFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/get.handler
Events:
GetItem:
Type: HttpApi
Properties:
ApiId: !Ref HttpApi
Path: /items/{id}
Method: GET
Policies:
- DynamoDBReadPolicy:
TableName: !Ref ItemsTable
CreateItemFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/create.handler
Events:
CreateItem:
Type: HttpApi
Properties:
ApiId: !Ref HttpApi
Path: /items
Method: POST
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref ItemsTable
# DynamoDB Table
ItemsTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
BillingMode: PAY_PER_REQUEST
Outputs:
ApiUrl:
Value: !Sub "https://${HttpApi}.execute-api.${AWS::Region}.amazonaws.com/prod"
// src/handlers/get.js
const { getItem } = require('../lib/dynamodb');
exports.handler = async (event) => {
const id = event.pathParameters?.id;
if (!id) {
return {
statusCode: 400,
body: JSON.stringify({ error: 'Missing id parameter' })
};
}
const item =
イベント駆動 SQS パターン
信頼性の高い非同期処理のために SQS でトリガーされる Lambda
使用する場面: ['疎結合で非同期の処理が必要な場合', 'リトライロジックと DLQ が必要な場合', 'メッセージをバッチで処理する場合']
```yaml
# template.yaml
Resources:
ProcessorFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/processor.handler
Events:
SQSEvent:
Type: SQS
Properties:
Queue: !GetAtt ProcessingQueue.Arn
BatchSize: 10
FunctionResponseTypes:
- ReportBatchItemFailures # Partial batch failure handling
ProcessingQueue:
Type: AWS::SQS::Queue
Properties:
VisibilityTimeout: 180 # 6x Lambda timeout
RedrivePolicy:
deadLetterTargetArn: !GetAtt DeadLetterQueue.Arn
maxReceiveCount: 3
DeadLetterQueue:
Type: AWS::SQS::Queue
Properties:
MessageRetentionPeriod: 1209600 # 14 days
// src/handlers/processor.js
exports.handler = async (event) => {
const batchItemFailures = [];
for (const record of event.Records) {
try {
const body = JSON.parse(record.body);
await processMessage(body);
} catch (error) {
console.error(`Failed to process message ${record.messageId}:`, error);
// Report this item as failed (will be retried)
batchItemFailures.push({
itemIdentifier: record.messageId
});
}
}
// Return failed items for retry
return { batchItemFailures };
};
async function processMessage(message) {
// Your processing logic
console.log('Processing:', message);
// Simulate work
await saveToDatabase(message);
}
# Python version
import json
import logging
logger = logging.getLogger()
def handler(event, context):
batch_item_failures = []
for record in event['Records']:
try:
body = json.loads(record['body'])
process_message(body)
except Exception as e:
logger.error(f"Failed to process {record['messageId']}: {e}")
batch_item_failures.append({
'itemIdentifier': record['messageId']
})
return {'batchItemFailures': batch_ite
アンチパターン
❌ モノリシックな Lambda
問題点: デプロイパッケージが大きいと、コールドスタートが遅くなります。 個々の処理を個別にスケールさせることが困難です。 更新がシステム全体に影響します。
❌ 大きな依存関係
問題点: デプロイパッケージのサイズが増加します。 コールドスタートが大幅に遅くなります。 SDK やライブラリの大部分が使われていない場合があります。
❌ VPC 内での同期呼び出し
問題点: VPC にアタッチされた Lambda では ENI のセットアップに余分なオーバーヘッドが発生します。 ブロッキングする DNS 参照や接続は、コールドスタートをさらに悪化させます。
⚠️ 注意すべきポイント
| 問題 | 重大度 | 解決策 |
|---|---|---|
| 問題 | 高 | ## INIT フェーズを計測する |
| 問題 | 高 | ## 適切なタイムアウトを設定する |
| 問題 | 高 | ## メモリ割り当てを増やす |
| 問題 | 中 | ## VPC 構成を確認する |
| 問題 | 中 | ## Lambda にイベントループの完了を待たないよう指示する |
| 問題 | 中 | ## 大きなファイルをアップロードする場合 |
| 問題 | 高 | ## バケットやプレフィックスを分ける |
コメント
Markdown 対応