「APIリクエストを通じてLambda関数を呼び出し、レスポンスを返す」という簡単な例を通じて Lambda
と API Gateway
の使い方を確認します。
作るもの
Lambda
はイベントに応じて、コードを実行できるサービスです。
今回は、API Gateway
で作成したAPIリクエストをトリガーにLambda関数を実行させます。最終的な動作イメージを示します。
/message?name=wakuwaku
というパスでリクエストを飛ばしたら、指定されたLambda関数が実行されます。- Lambda関数は
nameパラメーター
の内容を読み取りHello wakuwaku
という文字列をレスポンスとして返します。 - Lambda関数の実行ログは
CloudWatch
に保存されます。
Lambda関数作成
関数とロールの作成
Lambdaの管理画面を開き、関数の作成
をクリックします。
ランタイムとしてPython
Java
Go
などを利用できます。ここでは、Node.js 8.10
を利用します。
今回、Lambda関数を初めて作成するのですが、Lambda関数用のロールも作成しておきます。カスタムロールの作成
をクリックします。
カスタムロールの作成
をクリックしたので、IAMのページが開きました。そのまま許可
をクリックします。
Lambda関数の実行ログを保存するために、CloudWatch Logs
への書き込み権限を付与されています。
IAMページが閉じ、Lambda関数の作成ページに作成したロールが設定されました。関数の作成
をクリックします。
関数が生成されました。
上記画面で以下のような設定をすることができます。
- トリガーの追加
- 関数コードの編集
- メモリーの設定
- タイムアウトの設定
- 同時実行数の設定
トリガーの設定
今回は、APIリクエストをトリガーにLambda関数を実行させます。
トリガーの設定は、後述する API Gateway
の設定時に行います。
補足:代表的なユースケース
- cronのように定期実行したい
CloudWatch Events
を利用します。Cron式
ですが、通常のcronの指定方式より1つ指定項目が多くなっています(Year
)
- https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/tutorial-scheduled-events-schedule-expressions.html
- S3オブジェクトが作成されたときに実行したい
- APIリクエストで実行させたい
関数コードの編集
以下のコードを貼り付けます。
exports.handler = async (event) => {
console.log(event)
console.log(process.env)
const response = {
statusCode: 200,
body: 'Hello',
}
return response
}
環境変数の設定
環境変数を設定できます。ここでは動作確認用として以下のように設定しました。
動作確認
保存
がクリック済みか確認します。
テストイベントの設定
をクリックします。
関数実行時に渡されるevent
を設定します。
イベントが設定されました。テスト
をクリックすると関数が実行されます。
以下、実行結果です。
- ①
return response
で返した内容が表示されています。 - ②
console.log(event)
の出力結果です。作成したテストイベント
の内容が表示されています。 - ③
console.log(process.env)
の出力結果です。設定した環境変数の内容が表示されています。
API作成
APIの作成
API Gatewayの管理画面を開き、今すぐ始める
をクリックします。
新しいAPI
を選択します。API名を入力してAPIの作成をクリックします。
リソースの作成
リソースの作成
をクリックします。
今回は、messageというリソースを作成します。
メソッドの作成とLambda関数紐付け
メソッドの作成
をクリックします。
GETメソッドを選択します。
先ほど作成したLambda関数を選択します。
デプロイ
APIのデプロイ
をクリックします。
ステージ名を選択できます。開発環境、ステージ環境、本番環境といった使い分けができます。
今回はdev
というステージにします。
APIのエンドポイントが表示されます。動作確認でこのURLを利用します。
動作確認
curlで動作確認します。先ほどのURLに message
を追加して呼び出します。
$ curl https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/message
{"statusCode":200,"body":"Hello"}
Lambda関数の出力結果がレスポンスとして確認できました。
CloudWatchのログでLambda関数の実行ログを確認できます。
APIのパラメーターをLambda関数に渡す
console.log(event) の出力結果
( Before )
console.log(event)
の出力結果はCloudWatchのログで確認したところ以下のようになっていました。
2019-01-02T09:58:00.598Z e3639496-0e74-11e9-87d6-ed0437c0370d
{}
event
経由でリクエストパラメーターを渡せるように調整します。
Lambdaプロキシ統合の使用
Lambdaプロキシ統合の使用
にチェックを入れると、event
経由でリクエストパラメーターを渡せるようになります。
設定を変更したので、再度APIをデプロイします。
参考
- API Gateway の Lambda プロキシ統合をセットアップする
- 別の方法として、
マッピング
を作ることで、パラメータをLambda関数に渡すこともできます。
console.log(event) の出力結果
( After )
Lambdaプロキシ統合の使用
にチェックを入れたことによって、console.log(event)
の出力結果がどのように変わるのか確認します。
nameパラメーターを付与してAPIを呼び出します。
$ curl https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/message?name=wakuwaku
Hello
レスポンスとして、 Hello
のみが返るようになりました。
console.log(event)
の出力は以下のようになりました。
2019-01-02T10:17:03.844Z 8cd4bd30-0e77-11e9-b798-19091d0a23a5 { resource: '/message',
path: '/message',
httpMethod: 'GET',
headers:
{ accept: '*/*',
Host: 'xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com',
'User-Agent': 'curl/7.54.0',
'X-Amzn-Trace-Id': 'Root=XXXXXXXXXXXXXXXXXXXXXXXXXX',
'X-Forwarded-For': 'xxx.xxx.xxx.xxx',
'X-Forwarded-Port': '443',
'X-Forwarded-Proto': 'https' },
multiValueHeaders:
{ accept: [ '*/*' ],
Host: [ 'xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com' ],
'User-Agent': [ 'curl/7.54.0' ],
'X-Amzn-Trace-Id': [ 'Root=XXXXXXXXXXXXXXXXXXXXXXXXXX' ],
'X-Forwarded-For': [ 'xxx.xxx.xxx.xxx' ],
'X-Forwarded-Port': [ '443' ],
'X-Forwarded-Proto': [ 'https' ] },
queryStringParameters: { name: 'wakuwaku' },
multiValueQueryStringParameters: { name: [ 'wakuwaku' ] },
pathParameters: null,
stageVariables: null,
requestContext:
{ resourceId: 'xxxxxx',
resourcePath: '/message',
httpMethod: 'GET',
extendedRequestId: 'S3tg-XXXXXXXXXXX',
requestTime: '02/Jan/2019:10:17:03 +0000',
path: '/dev/message',
accountId: 'XXXXXXXXXXXXX',
protocol: 'HTTP/1.1',
stage: 'dev',
domainPrefix: 'xxxxxxxx',
requestTimeEpoch: XXXXXXXXXXXX,
requestId: 'XXXXXXXXXXXXXXXXXXXXXXX',
identity:
{ cognitoIdentityPoolId: null,
accountId: null,
cognitoIdentityId: null,
caller: null,
sourceIp: 'xxx.xxx.xxx.xxx',
accessKey: null,
cognitoAuthenticationType: null,
cognitoAuthenticationProvider: null,
userArn: null,
userAgent: 'curl/7.54.0',
user: null },
domainName: 'xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com',
apiId: 'xxxxxxxx' },
body: null,
isBase64Encoded: false }
Lambda関数のコードを修正
event.queryStringParameters
経由でリクエストパラメーターを取得できるようなのでLambda関数のコードを以下のように修正します。
exports.handler = async (event) => {
console.log(event)
console.log(process.env)
let name = 'no name'
if (event.queryStringParameters && event.queryStringParameters.name) {
name = event.queryStringParameters.name
}
const response = {
statusCode: 200,
body: `Hello ${name}`,
}
return response
}
APIを呼び出します。
$ curl https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/message?name=wakuwaku
Hello wakuwaku
Lambda関数内でリクエストパラメータを取得できたことを確認できました。
補足
料金について
リクエスト数、実行時間、割り当てたメモリサイズに応じて課金されます。
実際の開発
今回は、雰囲気をつかむために管理画面で操作しました。
実際の開発では、 Serverless Framework
や AWS Serverless Application Model(SAM)
などが利用されることが多いです。
- Serverless Framework
- Node.jsで書かれたCLIツールです。
- https://serverless.com/framework/docs/
- https://github.com/serverless/serverless
- AWS Serverless Application Model(SAM)
CloudFormation
を変形したものです。Lambda関数
API Gateway
DynamoDBテーブル
をまとめて定義できます。- https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/what-is-sam.html
- https://github.com/awslabs/serverless-application-model
各種制限
以下のような利用上の制限がいくつかあります。
- 関数のタイムアウト時間
- デプロイパッケージの容量
エラー時のリトライ
タイムアウトなどで失敗した場合のリトライ動作は、Lambda関数の呼び出し方法で異なります。
- ストリームベースではないイベントソース
- 同期呼び出し
- e.g.
- API Gateway(デフォルト動作)
- Alexa
- 呼び出し側(アプリ)にエラーを返す。必要があれば、アプリでリトライを実装する。
- e.g.
- 非同期呼び出し(キューイングされてから実行)
- e.g.
- API Gateway(ヘッダでEvent指定時)
- CloudWatch Events
- S3
- 最大2回自動的に再試行(つまり、合計3回実行される可能性がある)
- e.g.
- 同期呼び出し
- ストリームベースのイベントソース
- e.g.
- DynamoDBとLambdaを連携する場合
- データの有効期限が切れるか処理が成功するまで無限にリトライ
- e.g.