![見出し画像](https://assets.st-note.com/production/uploads/images/158643627/rectangle_large_type_2_f1108d4d59fe590635133c5318f3a5e6.png?width=1200)
CDKを使ってAPI GatewayとLambdaを作成する
はじめに
前回はCDKの基本的な実行方法を整理しました。
今回はAPIGatwayとLambdaを作成して連携させるCDKを記載します。
作成する構成
APIGatwayのリソースを2つ用意し、/syncの場合はLambdaを同期実行、/asyncの場合は非同期実行とする構成とします
![](https://assets.st-note.com/img/1729399269-ip2efsHPyCIkntS3avczdgTJ.png)
スタックの作成
Lambdaはsrc/sample-lambda.tsで定義します。
APIGatwayについて、同期/非同期で紐付け方が変わります。
違いについてはコードの下に記載します。
import * as cdk from 'aws-cdk-lib'
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
import { Construct } from 'constructs';
import * as path from 'path'
export class CdkSampleStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const lambda = new NodejsFunction(this, 'SampleLambda', {
functionName: 'SampleLambda',
entry: path.join(__dirname, '../src/sample-lambda.ts'),
handler: 'handler',
runtime: cdk.aws_lambda.Runtime.NODEJS_18_X,
timeout: cdk.Duration.seconds(180),
bundling: {
forceDockerBundling: false,
}
})
const api = new apigateway.RestApi(this, 'SampleLambdaApi', { cloudWatchRole: false })
// 同期呼び出しの設定
api.root.addResource('sync').addMethod(
'POST', new apigateway.LambdaIntegration(lambda))
// 非同期呼び出しの設定
api.root.addResource('async').addMethod(
'POST', new apigateway.LambdaIntegration(lambda,
{
proxy: false,
requestParameters: {
'integration.request.header.X-Amz-Invocation-Type': "'Event'"
},
integrationResponses: [
{ statusCode: '202', },
{ selectionPattern: '5\\d{2}', statusCode: '500', }
]
}),
{
methodResponses: [
{ statusCode: '202', },
{ statusCode: '500', }
],
})
}
}
非同期の場合、4点を設定する必要があります。
(1) proxyをfalseにします。これによってAPIGatwayの統合リクエスト設定にあるLambdaプロキシ統合がfalseになります。
![](https://assets.st-note.com/img/1729399732-pD2rIdw03oqAhvlEixzatBLu.png)
(2) requestParametersでLambdaに渡すヘッダにintegration.request.header.X-Amz-Invocation-Typeを'Event'を追加します。この設定によりLambdaが非同期実行されます。 ※(1)を設定しないと本設定でLambdaを実行するとエラーになります
(3) integrationResponsesで202を設定します。同期の場合はLambdaのレスポンスを返せば良いのですが、非同期の場合は自分でレスポンスを設定する必要があり、本設定によって統合レスポンスが設定されます。
なおHTTPで202はリクエスト受理を表し、ここではLambda実行まで行なったことを表します。
![](https://assets.st-note.com/img/1729400258-g8xTojGNkFWvpS6sfOlb7mMR.png)
(4) methodResponsesで202を設定します。メソッドレスポンスの設定になり、(3)の内容と整合性を取ります。
![](https://assets.st-note.com/img/1729400459-1QdlMhVYLPnBOWbSsoNarU6u.png)
Lambdaの作成
Lambdaの内部にスリープを入れて処理を送らせることで同期・非同期を区別しやすいコードを作成します。
import { APIGatewayEvent, APIGatewayProxyResult, Context } from 'aws-lambda'
export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => {
console.log(`Event: ${JSON.stringify(event, null, 2)}`)
console.log(`Context: ${JSON.stringify(context, null, 2)}`)
const sleep = (time: number) => new Promise((resolve) => setTimeout(resolve, time));
const log = async () => {
await sleep(500);
for (let i = 0; i < 10; i++) {
console.log('i=' + i);
await sleep(500);
}
return 'test end!'
};
// 処理
const res = await log();
console.log('return response');
return {
statusCode: 200,
body: JSON.stringify({
message: 'Finish!',
}),
}
}
CDKでデプロイ
cdk deploy --profile プロファイル名
動作確認
同期実行を以下で確認します。
curl -i -X POST エンドポイント/sync -d '{"id": 123456789, "name":"Sample"}'
curlコマンドのレスポンスは以下となり、Cloud WatchからもLambda完了後にレスポンスを返していることが分かります。
HTTP/2 200
content-type: application/json
content-length: 21
date: Sun, 20 Oct 2024 05:06:10 GMT
以下省略
![](https://assets.st-note.com/img/1729401169-Usc3nSGzPyViHwh6YNxtqMIb.png?width=1200)
次に非同期実行を確認します。
curl -i -X POST エンドポイント/async -d '{"id": 123456789, "name":"Sample"}'
curlコマンドのレスポンスは以下となり、APIGatwayのレスポンスは即時であり、非同期でLambdaが実行されていることが分かります。
HTTP/2 202
content-type: application/json
content-length: 0
date: Sun, 20 Oct 2024 05:10:55 GMT
![](https://assets.st-note.com/img/1729401127-LzaFscteDHX56iClRB7mVWwo.png?width=1200)
まとめ
CDKの構築でLambdaの実行を同期/非同期に切り替えられることが分かりました。
そもそもにおいてLambdaは内部で非同期となるコードを書いてもLambdaが応答を返すタイミングで処理が終了してしまい、非同期側も止まってしまいます。
一方でAPIGatwayはリクエストから29秒以内にレスポンスを返さないとエラーになる制約があり、Lambdaが完了するまで待ち続けることができません。
そのため今回のようにAPIGatwayからLambdaを非同期で実行するか、APIGatway→Lambda→SQS→Lambdaの用にSQSを間に挟む構成になります。
※APIGatway→Lambda→Lambdaは拡張性の面で望ましくない
今回は単純にLambdaが実行できれば良い場合に用いる方法であり、逆に言えばLambdaを実行しっぱなしになるため、業務で必要な事前チェックなどは実現できません。そのため必要に応じてSQSを挟む構成との選択が必要となります。