SQS(FIFO) - Lambda構成の備忘録

# SQS(FIFO) - Lambda構成の備忘録

AWS歴5-6年なのにSQSを一度も触ったことがなく。。。
AssociateやPro資格は全て取得したので、多少のドキュメントレベルの知識ならあると思うんですが。
触る経験がないことが心残りでした。  

そんな中、やっとSQSのキュートリガーを使ったLambdaの構成を検証する機会が舞い降りたので！
自分の備忘録がてらにメモを残します。

## 構成

![screenshot.78.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236355/eaf3b382-52b8-ef0a-a5cf-ff65b38ccffa.jpeg)


## CFnコード(yaml)

### IAM Role

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: [TEST] IAM Role for Lambda.
Parameters:
  RoleName:
    Type: String
    Default: test-lambdarole

Resources:
  LambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          Effect: Allow
          Principal:
            Service: lambda.amazonaws.com
          Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaSQSQueueExecutionRole
        - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
      RoleName: !Ref RoleName
      Tags:
        - Key: Name
          Value: !Ref RoleName
```

### SQS

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: [TEST] FIFO SQSQueue, DLQ

Parameters:
  QueueName:
    Type: String
    Description: SQS Name
    Default: test-sqs.fifo
  DLQName:
    Type: String
    Description: SQS Name
    Default: test-dlq.fifo

Resources:
  SQS:
    Type: AWS::SQS::Queue
    Properties:
      ContentBasedDeduplication: true
      DeduplicationScope: queue
      FifoQueue: true
      FifoThroughputLimit: perQueue
      QueueName: !Ref QueueName
      RedrivePolicy:
        deadLetterTargetArn: !GetAtt SQSDLQueue.Arn
        maxReceiveCount: 1
      Tags:
      - Key: Name
        Value: !Red QueuName
      VisibilityTimeout: 300
    DependsOn: SQSDLQueue01

  SQSPolicy:
    Type: AWS::SQS::QueuePolicy
    Properties: 
      PolicyDocument:
        Version: '2008-10-17'
        Id: __default_policy_ID
        Statement:
          - Sid: __owner_statement
            Effect: Allow
            Principal:
              AWS: !Sub arn:aws:iam::${AWS::AccountId}:root
            Action: SQS:*
            Resource: !GetAtt SQS.Arn
      Queues: 
        - !GetAtt SQS.QueueName
    DependsOn: SQS

  SQSDLQueue:
    Type: AWS::SQS::Queue
    Properties:
      ContentBasedDeduplication: false
      DeduplicationScope: queue
      FifoQueue: true
      FifoThroughputLimit: perQueue
      QueueName:  sqs-dlq.fifo
      RedriveAllowPolicy:
        redrivePermission: allowAll
      Tags:
      - Key: Name
        Value: !Red DLQName
      VisibilityTimeout: 300

  SQSDLQueuePolicy:
    Type: AWS::SQS::QueuePolicy
    Properties:
      PolicyDocument:
        Version: '2008-10-17'
        Id: __default_policy_ID
        Statement:
          - Sid: __owner_statement
            Effect: Allow
            Principal:
              AWS: !Sub arn:aws:iam::${AWS::AccountId}:root
            Action: SQS:*
            Resource: !GetAtt SQSDLQueue.Arn
      Queues:
        - !GetAtt SQSDLQueue.QueueName
    DependsOn: SQSDLQueue
Outputs:
  SQS:
    Description: ARN of the SQS Queue we created
    Value:
      !GetAtt SQS.Arn
  SQSDLQueue:
    Description: ARN of the SQS Dead-letter Queue we created
    Value:
      !GetAtt SQSDLQueue.Arn
```

### Lambda

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: [TEST] Queu Trigger Lambda
Parameters:
  SubnetID01:
    Type: String
    Default: ''
  SecurityGroupID:
    Type: String
    Default: ''
  LambdaName:
    Type: String
    Default: test-lambda
  S3BucketName:
    Type: String
    Default: test-dammycode-s3
  SQSName:
    Type: String
    Default: test-sqs.fifo
  RoleName:
    Type: String
    Default: test-lambdarole

Resources:
  Lambda:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Red LambdaName
      Runtime: java11
      Handler: lambda_function.lambda_handler
      Timeout: 50
      PackageType: Zip
      Code:
        S3Bucket: !Red S3BucketName
        S3Key: dammy_lambdacode.zip
      Role: !Sub arn:aws:iam::${AWS::AccountId}:role/${RoleName}
      VpcConfig: 
        SubnetIds: 
          - !Ref SubnetID01
        SecurityGroupIds: 
          - !Ref SecurityGroupID
      Tags:
        - Key: Name
          Value: !Ref LambdaName

  LambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref Lambda
      Action: lambda:InvokeFunction
      Principal: sqs.amazonaws.com
      SourceAccount: !Ref AWS::AccountId
      SourceArn: !Sub arn:aws:sqs:ap-northeast-1:${AWS::AccountId}:${SQSName}

  LambdaEventSourceMapping:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      EventSourceArn: !Sub arn:aws:sqs:ap-northeast-1:${AWS::AccountId}:${SQSName}
      FunctionName: !GetAtt Lambda.Arn
      BatchSize: "10"
      Enabled: true
    DependsOn: Lambda
```

## 処理時間やバッチサイズに関する備忘録

- 可視性タイムアウト
可視性タイムアウトは、処理されたメッセージを見えないようにする時間で、重複処理防止の為のもの
- 可視性タイムアウトの処理時間とLambdaの実行時間の関係
可視性タイムアウトの処理時間はLambdaの実行時間の6倍の時間を設定することがAWSより推奨されている
- バッチサイズ
Lambdaが1回の処理で、SQSから取得してくるメッセージの数


[例]
以下の条件で、SQSの可視性タイムアウトの処理時間とバッチサイズを設定する場合
 [Lambda内で実施される処理の時間：10秒未満]
 [Lambdaの処理時間：60秒]

SQSの可視性タイムアウトの処理時間は360秒以上、バッチサイズは6以下になる。

※Lambdaの処理時間等はアプリケーションとの兼ね合いであったり、テストしながらのチューニングの必要性があると思うので、上記はあくまでも筆者の備忘と思って下さい。

## その他

- Queu Trigger
Queue Triggerの場合、LambdaからSQSに対してポーリングしているので、今回利用したVPC配置Lambdaの場合、インバウンドは穴あけする必要がなく、アウントバウンドのみの設定で済んだ

## 参考
英語のドキュメントですが、バッチサイズ周りの考え方など図示されていて分かりやすく、めっちゃ参考になりました。
筆者は本当に簡単な内容しか上記に記載してませんが、メッセージの処理される順番(IDなども含めた)など、細かく記載されているので、見てみて下さい。
[New for AWS Lambda – SQS FIFO as an event source](https://aws.amazon.com/jp/blogs/compute/new-for-aws-lambda-sqs-fifo-as-an-event-source/)