Serverless Frameworkを使ってsqs+lambda

# はじめに
仕事でsqs+lambdaを使って非同期処理を実装したので、復習がてら記事にしています。
本当は、 DLQを設定してDLQに入るとCloudWatchからslackに通知を飛ばすという風にしたかったのですが、上手くいかなかったので、追記するか別記事にしようと思います。

# Serverless Frameworkからプロジェクトの作成
まず、Serverless Frameworkをインストールします。

```
@ueMac [~/dev]
[ueyuki]-> npm install -g serverless

@ueMac [~/dev]
[ueyuki]-> serverless -v
Framework Core: 1.74.1
Plugin: 3.6.15
SDK: 2.3.1
Components: 2.31.11
```

Serverless Frameworkでは、テンプレートを使用してプロジェクトを作成することができます。
今回は、lambdaでgoを使っていくので、goのテンプレートを使用します。

```
@ueMac [~/dev]
[ueyuki]-> serverless create -u https://github.com/serverless/serverless-golang/ -p go-sqs-lambda
Serverless: Generating boilerplate...
Serverless: Downloading and installing "serverless-golang"...
Serverless: Successfully installed "serverless-golang"
```

必要なパッケージをgo getします。

```
@ueMac [~/dev/go-sqs-lambda]
[ueyuki]-> go get github.com/aws/aws-lambda-go/lambda
```

# lambdaの実装
デフォルトで作成されたmain.goは以下のようになっています。

```go:main.go
package main

import (
	"github.com/aws/aws-lambda-go/lambda"
)

type Response struct {
	Message string `json:"message"`
}

func Handler() (Response, error) {
	return Response{
		Message: "Go Serverless v1.0! Your function executed successfully!",
	}, nil
}

func main() {
	lambda.Start(Handler)
}
```
今回は、sqsから呼ばれて関数を実行したいため、以下のように変更します。

```go:main.go
package main

import (
	"context"
	"fmt"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

type Response struct {
	Message string `json:"message"`
}

func Handler(ctx context.Context, sqsEvent events.SQSEvent) error {
	for i := range sqsEvent.Records {
		record := sqsEvent.Records[i]
		message := record.Body
		fmt.Println(message)
	}
	return nil
}

func main() {
	lambda.Start(Handler)
}

```

# serverless.yml
serverless.ymlを設定します。

```yml:serverless.yml
service: go-sqs-lambda

provider:
  name: aws
  runtime: go1.x
  stage: dev
  region: ap-northeast-1

package:
 exclude:
   - ./**
 include:
   - ./bin/**

functions:
  hello:
    handler: bin/main

functions:
  goQueueWorker:
    name: go-queue-worker
    handler: bin/go-handler
    timeout: 30
    memorySize: 1024
    reservedConcurrency: 1
    events:
      - sqs:
          arn: arn:aws:sqs:ap-northeast-1:{accountId}:go-queue
          batchSize: 1

resources:
 Resources:
   MyQueue:
     Type: "AWS::SQS::Queue"
     Properties:
       QueueName: "go-queue-by-serverless"
```

# 確認

まず、デプロイします。

```
@ueMac [~/dev/go-sqs-lambda]
[ueyuki]-> sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service go-sqs-lambda.zip file to S3 (6.22 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
.........
Serverless: Stack update finished...
Service Information
service: go-sqs-lambda
stage: dev
region: ap-northeast-1
stack: go-sqs-lambda-dev
resources: 8
api keys:
  None
endpoints:
  None
functions:
  goQueueWorker: go-queue-worker
layers:
  None
Serverless: Removing old service artifacts from S3...
```

成功したようなので、メッセージを送ってみましょう。

```
@ueMac [~/dev/go-sqs-lambda]
[ueyuki]-> aws sqs send-message --queue-url https://ap-northeast-1.queue.amazonaws.com/434383646091/go-queue-by-serverless --message-body "ああああああああああああああああああああ"
{
    "MD5OfMessageBody": "ea177a7ff3db26cb8928d1c895e873f1",
    "MessageId": "37ebf278-519f-4438-8dee-e57f7072b131"
}
```

ログを確認してみると、

```
@ueMac [~/dev/go-sqs-lambda]
[ueyuki]-> sls logs -f goQueueWorker
START RequestId: a26e00fe-dbfb-56c4-b0c3-5764138a8ce4 Version: $LATEST
ああああああああああああああああああああ
END RequestId: a26e00fe-dbfb-56c4-b0c3-5764138a8ce4
REPORT RequestId: a26e00fe-dbfb-56c4-b0c3-5764138a8ce4	Duration: 0.40 ms	Billed Duration: 100 ms	Memory Size: 1024 MB	Max Memory Used: 25 MB
```

想定通り動いていそうです。