マイナビニュースマイナビ

AWS Lambdaにおけるサーバレスエラーハンドリング(3)

【連載】

AWSで作るクラウドネイティブアプリケーションの応用

【第8回】AWS Lambdaにおけるサーバレスエラーハンドリング(3)

[2021/04/05 08:00]川畑光平 ブックマーク ブックマーク

本連載では、AWS Lambdaを使ったサーバレス処理でのエラーハンドリング方法を解説しています。前回は数の赤い矢印のスコープにおいて、同期型でビジネスエラーが発生することを想定したSpring Cloud Function 3.1以降のLambdaファンクションの実装方法やパッケージ構成について解説しました。

構成図

今回はAPI GatewayとLambda実行環境をCloudFormationを使って構築し、同期的にLambdaを呼び出してみます。

なお、API Gatewayおよび、Lambdaをマネジメントコンソール上から手動で構築する場合は、連載「AWSで作るクラウドネイティブアプリケーションの基本」の第2回第3回と同一です。設定内容はほぼ同じなので、構築に必要な設定要素を理解するにはこちらも参照することをお薦めします。 また、CloudFormationを使った環境構築の説明は割愛しますが、基本的なお作法は連載「AWSで実践! 基盤構築・デプロイ自動化」の第21回以降で解説しているので、適宜参照してください。

LambdaファンクションのCloudFormationテンプレート

AWS LambdaをCloudFormationで構築するときのテンプレートの記述要領については、連載「AWSで実践! 基盤構築・デプロイ自動化」の第42回を参照してください。事前にLambdaをデプロイするためにビルドされたアプリケーションパッケージを配置するS3バケットを作成しておきます。また、Lambdaのテンプレートから参照するので、バケット名やARNをエクスポートします。

AWSTemplateFormatVersion: '2010-09-09'

Description: S3 Bucket for Lambda function template with YAML - S3 Bucket Definition

Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: debugroom-mynavi-sample-lambda-errorhandling-for-deploy
      AccessControl: Private
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True

Outputs:
  S3Bucket:
    Description: Lambda deploy S3 bucket name
    Value: !Ref S3Bucket
    Export:
      Name: debugroom-mynavi-sample-lambda-errorhandling-deploy-s3-bucket

  S3BucketArn:
    Description: Deploy S3 for Lambda bucket arn
    Value: !GetAtt S3Bucket.Arn
    Export:
      Name: debugroom-mynavi-sample-lambda-errorhandling-deploy-s3-bucket-arn

続いて、前回実装したLambdaファンクションをビルドして、このバケットにアップロードしますが、以下のようなスクリプトを実行すると簡易です。Java仮想マシンのルートディレクトリとなるJAVA_HOME環境変数やMavenのビルドコマンドのパスなどは、適宜自分の環境に合わせて書き換えてください。なお、コマンドを実行するためのAWS CLIのインストールや開発端末の認証情報の設定は、連載「AWSで実践! 基盤構築・デプロイ自動化」の第22回で解説した手順に沿って行っておくとよいでしょう。

#!/usr/bin/env bash

export JAVA_HOME=/usr/lib/jvm/java-11-amazon-corretto.x86_64
bucket_name="debugroom-mynavi-sample-lambda-errorhandling-for-deploy"
stack_name="mynavi-sample-deploy-s3-for-lambda-errorhandling"
template_path="cloudformation/1-s3-for-lambda-deploy-cfn.yml"
s3_objectkey="spring-cloud-3-1-lambda-function-0.0.1-SNAPSHOT-aws.jar"

if [ "" == "`aws s3 ls | grep $bucket_name`" ]; then
    aws cloudformation deploy --stack-name ${stack_name} --template-file ${template_path} --capabilities CAPABILITY_IAM
fi

cd spring-cloud-3-1-lambda-function
./mvnw clean package
aws s3 cp target/${s3_objectkey} s3://${bucket_name}/

続いて、Lambda実行環境のCloudFormationテンプレートを実装します。

AWSTemplateFormatVersion: '2010-09-09'

#omit

Resources:
  LambdaForSyncExecuteBusinessErrorFuntion:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        S3Bucket:
          Fn::ImportValue: debugroom-mynavi-sample-lambda-errorhandling-deploy-s3-bucket  #(1)
        S3Key: spring-cloud-3-1-lambda-function-0.0.1-SNAPSHOT-aws.jar
      Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest #(2)
      FunctionName: mynavi-sample-aws-lambda-errorhandling-sync-business-error
      Environment:
        Variables:
          SPRING_CLOUD_FUNCTION_DEFINITION: syncExecuteBusinessErrorFunction #(3)
      MemorySize: 1024
      Runtime: java11
      Timeout: 120
      Role: !GetAtt LambdaRole.Arn #(4)

  #omit

  LambdaRole:
    Type: AWS::IAM::Role
    Properties:
      Path: /
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            ManagedPolicyArns:
              - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole

  #omit

Outputs:
  #omit

  LambdaForSyncExecuteBusinessErrorFuntion: #(5)
    Description: Sync execute Lambda function for occuring business error function.
    Value: !Ref LambdaForSyncExecuteBusinessErrorFuntion
    Export:
      Name: mynavi-sample-lambda-errorhandling-sync-execute-business-error-function-name

  LambdaForSyncExecuteBusinessErrorFuntionArn: #(6)
    Description: Sync execute Lambda function for occuring business error function.
    Value: !GetAtt LambdaForSyncExecuteBusinessErrorFuntion.Arn
    Export:
      Name: mynavi-sample-lambda-errorhandling-sync-execute-business-error-function-arn

  #omit

Lambdaテンプレートのポイントの詳細は以下の通りです。

項番 説明
1 S3Bucketは上述したデプロイ用のS3を構築したテンプレートでエクスポートしたS3のバケット名をクロススタックリファレンス参照します
2 リクエストのハンドラとして、org.springframework.cloud.function.adapter.aws.FunctionInvokerを指定します
3 環境変数SPRING_CLOUD_FUNCTION_DEFINITIONに、前回実装したファンクションのBean名を指定します
4 構築するLambdaファンクションに実行に必要なロールを設定します
5 後述するAPI Gatewayの設定時に必要なLambdaファンクション名をエクスポートしておきます
6 後述するAPI Gatewayの設定時に必要なLambdaファンクションのARNをエクスポートしておきます

API GatewayのCloudFormationテンプレート

続いて、Lambdaファンクションを呼び出すAPI GatewayのCloudformationテンプレートを実装します。

AWSTemplateFormatVersion: '2010-09-09'

#omit

Resources:
  ApiGatewayRestApi: #(1)
    Type: "AWS::ApiGateway::RestApi"
    Properties:
      Name: "mynavi-sample-lambda-errorhandling-rest-api"
      Description: "Mynavi sample sync execute function API"

  ApiGatewayDeployment: #(2)
    Type: "AWS::ApiGateway::Deployment"
    DependsOn:
      - ApiGatewayBusinessExceptionMethod
    Properties:
      RestApiId:
        Ref: ApiGatewayRestApi

  ApiGatewayStage: #(3)
    Type: "AWS::ApiGateway::Stage"
    Properties:
      StageName: "dev"
      Description: "dev stage"
      RestApiId:
        Ref: ApiGatewayRestApi
      DeploymentId:
        Ref: ApiGatewayDeployment

  ApiGatewayModel: #(4)
    Type: "AWS::ApiGateway::Model"
    Properties:
      RestApiId:
        Ref: ApiGatewayRestApi
      ContentType: "application/json"
      Name: SampleSchema
      Schema:
        "$schema": "http://json-schema.org/draft-04/schema#"
        title: SampleResource  #(5)
        type: object
        properties:
          message:
            type: string

  ApiGatewayBusinessExceptionResource:  #(6)
    Type: "AWS::ApiGateway::Resource"
    Properties:
      RestApiId:
        Ref: ApiGatewayRestApi
      ParentId:
        Fn::GetAtt:
          - ApiGatewayRestApi
          - RootResourceId
      PathPart: "business-exception-sample-resource"

   #omit

  ApiGatewayBusinessExceptionMethod: #(7)
    Type: "AWS::ApiGateway::Method"
    DependsOn: ApiGatewayModel
    Properties:
      RestApiId:
        Ref: ApiGatewayRestApi
      ResourceId:
        Ref: ApiGatewayBusinessExceptionResource
      HttpMethod: "GET"
      AuthorizationType: "NONE"
      Integration:
        Type: "AWS_PROXY"  #(8)
        Uri:  #(9)
          Fn::Join:
            - ""
            - - "arn:aws:apigateway"
              - ":"
              - Ref: AWS::Region
              - ":"
              - "lambda:path/2015-03-31/functions/"
              - Fn::ImportValue: mynavi-sample-lambda-errorhandling-sync-execute-business-error-function-arn
              - "/invocations"
        IntegrationHttpMethod: "POST"
        IntegrationResponses:
          - StatusCode: 400
            SelectionPattern: 400
          - StatusCode: 200
        PassthroughBehavior: WHEN_NO_MATCH
      MethodResponses:  #(10)
        - StatusCode: 200
          ResponseModels:
            application/json: SampleSchema
        - StatusCode: 400
          ResponseModels:
            application/json: Error

  #omit

  ApiGatewayUsagePlan: #(11)
    Type: AWS::ApiGateway::UsagePlan
    Properties:
      ApiStages:
        - ApiId:
            Ref: ApiGatewayRestApi
          Stage:
            Ref: ApiGatewayStage
      Quota:
        Limit: 100
        Period: DAY
      Throttle:
        BurstLimit: 10
        RateLimit: 2
      UsagePlanName: "SampleUsagePlan"

  BusinessErrorLambdaPermission: #(12)
    Type: "AWS::Lambda::Permission"
    Properties:
      FunctionName:
        Fn::ImportValue: mynavi-sample-lambda-errorhandling-sync-execute-business-error-function-name
      Action: "lambda:InvokeFunction"
      Principal: "apigateway.amazonaws.com"

API Gatewayテンプレートのポイントの詳細は以下の通りです。

項番 説明
1 API GatewayでRestAPIを定義します。各プロパティの詳細はAWS::ApiGateway::RestApiを参照してください
2 API GatewayでRestAPIをデプロイさせた状態で構築します。各プロパティの詳細は AWS::ApiGateway::Deploymentを参照してください
3 API GatewayでRestAPIをデプロイさせるためのステージを定義します。各プロパティの詳細は AWS::ApiGateway::Stageを参照してください。ここでステージは開発用の"dev"を定義しておきます
4 API Gateway RestAPIで返却するモデルを定義します。各プロパティの詳細はAWS::ApiGateway::Modelを参照してください
5 モデルのスキーマとして、前回実装したリソースクラスSampleResourceおよびそのプロパティを定義します
6 API Gatewayが返却するリソースやパスを定義します。各プロパティの詳細はAWS::ApiGateway::Resourceを参照してください
7 Rest APIのメソッドを定義します。各プロパティの詳細はAWS::ApiGateway::Methodを参照してください
8 API GatewayからLambdaへリクエストを転送する際のリクエストデータの変換方法を統合モデルとして定義します。Spring Cloud Functionでは、「Lambdaプロキシ統合」である設定値"AWS_PROXY"を前提としています。なお、Lambdaプロキシ統合の詳細については、 AWS公式ページ「API Gateway で Lambda プロキシ統合を設定する」 も参照してください
9 実行するLambdaファンクションのURIを定義します。前節のLambdaテンプレートで出力したファンクションのARNをクロススタックリファレンスで参照し、URIをJOIN関数で構築します
10 Lambda統合オプションでLambdaから返却されたアウトプットデータをAPI Gatewayでレスポンスデータとして変換する方法を定義します。正常終了時には5で定義したモデルクラスを返却し、ビジネスエラーが発生する400の場合は、デフォルトでAPI Gatewayが用意しているモデルErrorスキーマを用いてマッピングします
11 RestAPIのリクエスト量を調整する使用プランを定義します。使用量プランは、APIごとにスロットリングとクォータ制限が適用されます。各プロパティの詳細はAWS::ApiGateway::UsagePlanを参照してください
12 API GatewayがLambda関数を呼び出すのに必要な権限を定義します。各プロパティの詳細はAWS::Lambda::Permissionを参照してください

作成したテンプレートをCLIから実行すると、環境が構築されます。マネジメントコンソール上で、以下のように作成したリソースのメソッドを選択し、赤枠で囲まれたテストを選択してください。

テストを選択

クエリ文字列を指定しない状態で「テスト」ボタンを押下すると、ステータスコード400で返却されます。何かしらの文字列を指定すると、ステータスコード200で正常応答します(なお、初回の実行はLambdaの起動でタイムアウトになるケースもあります)。

結果

* * *

今回は、CloudFormationを使ってAPI GatewayとLambdaを構築し、Lambdaを同期的に呼び出してビジネスエラーを発生させ、エラーに応じてステータスコードが適切にマッピングするように設定する例を解説しました。次回以降は、同じくAPI GatewayとLambdaを使用した同期呼び出しで、システムエラーが発生した際に、CloudWatchに出力されたエラーログを契機として、システム管理者へ通知を行う実装を含めて解説していきます。

著者紹介


川畑 光平(KAWABATA Kohei) - NTTデータ
エグゼクティブ ITスペシャリスト ソフトウェアアーキテクト・デジタルテクノロジーストラテジスト(クラウド)

金融機関システム業務アプリケーション開発・システム基盤担当、ソフトウェア開発自動化関連の研究開発を経て、デジタル技術関連の研究開発・推進に従事。

Red Hat Certified Engineer、Pivotal Certified Spring Professional、AWS Certified Solutions Architect Professional等の資格を持ち、アプリケーション基盤・クラウドなど様々な開発プロジェクト支援にも携わる。AWS Top Engineers & Ambassadors選出。

本連載の内容に対するご意見・ご質問は Facebook まで。

※ 本記事は掲載時点の情報であり、最新のものとは異なる場合がございます。予めご了承ください。

一覧はこちら

連載目次

関連リンク

この記事に興味を持ったら"いいね!"を Click
Facebook で TECH+ の人気記事をお届けします
注目の特集/連載
[解説動画] Googleアナリティクス分析&活用講座 - Webサイト改善の正しい考え方
Slackで始める新しいオフィス様式
Google Workspaceをビジネスで活用する
ニューノーマル時代のオウンドメディア戦略
ミッションステートメント
次世代YouTubeクリエイターの成長戦略
IoTでできることを見つけるための発想トレーニング
教えてカナコさん! これならわかるAI入門
AWSではじめる機械学習 ~サービスを知り、実装を学ぶ~
Kubernetes入門
SAFeでつくる「DXに強い組織」~企業の課題を解決する13のアプローチ~
マイクロサービス時代に活きるフレームワーク Spring WebFlux入門
AWSで作るマイクロサービス
マイナビニュース スペシャルセミナー 講演レポート/当日講演資料 まとめ
セキュリティアワード特設ページ

一覧はこちら

今注目のIT用語の意味を事典でチェック!

一覧はこちら

会員登録(無料)

ページの先頭に戻る