使用Localstack在Golang中处理单个AWS Lambda处理器

290 阅读2分钟

多年来,我们一直投入大量的个人时间和精力,与大家分享我们的知识。然而,我们现在需要你的帮助来维持这个博客的运行。你所要做的只是点击网站上的一个广告,否则它将由于托管等费用而不幸被关闭。谢谢你。

在这个例子中,我们将创建一个Golang应用程序,其中有一个单一的AWS Lambda处理器。该函数将采用zip形式,接受一个JSON请求。也会有一个JSON响应,它将被写入一个文件中。对于所有这些操作,我们将使用一个Localstack实例。欲了解更多信息,请访问AWS Lambda CLI页面。

前提条件

使用下面的内容设置你的docker compose文件并运行它。运行后,拉出lambci/lambda:go1.x docker镜像,以便使用Localstack对Lambda进行操作。

version: "2.1"

services:
  localstack:
    image: "localstack/localstack"
    container_name: "localstack"
    ports:
      - "4566-4599:4566-4599"
    environment:
      - DEBUG=1
      - DEFAULT_REGION=eu-west-1
      - SERVICES=lambda
      - DATA_DIR=/tmp/localstack/data
      - DOCKER_HOST=unix:///var/run/docker.sock
#      - LAMBDA_EXECUTOR=docker
    volumes:
      - "/tmp/localstack:/tmp/localstack"
      - "/var/run/docker.sock:/var/run/docker.sock"

文件

main.go

package mainpackage main

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

func main() {
	lambda.Start(user.Create)
}

user/create.go

package user

import (
	"context"
	"fmt"
	"time"

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

type CreateRequest struct {
	FirstName string `json:"first_name"`
	LastName  string `json:"last_name"`
}

type CreateResponse struct {
	OK    bool   `json:"ok"`
	ID    int64  `json:"id"`
	ReqID string `json:"req_id"`
}

// Create creates a new user and returns its ID. If the request context was
// cancelled/timed out before proceeding to run the business logic, it will
// return an error. The timeout can be found in `Timeout` parameter of the lambda
// function. Defaults to 3 sec.
func Create(ctx context.Context, request CreateRequest) (CreateResponse, error) {
	select {
	case <-ctx.Done():
		return CreateResponse{OK: false, ID: 0}, fmt.Errorf("request timeout: %w", ctx.Err())
	default:
	}

	var reqID string
	if lc, ok := lambdacontext.FromContext(ctx); ok {
		reqID = lc.AwsRequestID
	}

	if request.FirstName == "" || request.LastName == "" {
		return CreateResponse{OK: false, ID: 0, ReqID: reqID}, fmt.Errorf("missing first or last name")
	}

	return CreateResponse{OK: true, ID: time.Now().UnixNano(), ReqID: reqID}, nil
}

设置

建立二进制文件

// I am using MacOS
$ GOOS=linux CGO_ENABLED=0 go build -ldflags "-s -w" -o app main.go

压缩二进制文件

$ zip app.zip app

创建函数

$ aws --profile localstack --endpoint-url http://localhost:4566 lambda create-function --function-name user-create --handler app --zip-file fileb://app.zip --runtime go1.x --role some-role --description "Creates a new user"

{
    "FunctionName": "user-create",
    "FunctionArn": "arn:aws:lambda:eu-west-1:000000000000:function:user-create",
    "Runtime": "go1.x",
    "Role": "some-role",
    "Handler": "app",
    "CodeSize": 2380470,
    "Description": "Creates a new user",
    "Timeout": 3,
    "LastModified": "2021-12-29T17:12:57.199+0000",
    "CodeSha256": "chRYxmVCd5ufDOrxui3kAUJZsCcp6WZn4LsMElZHIRg=",
    "Version": "$LATEST",
    "VpcConfig": {},
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "db7a03d0-cbda-4081-8b1a-0dc598c4ea34",
    "State": "Active",
    "LastUpdateStatus": "Successful",
    "PackageType": "Zip"
}

调用函数

$ aws --profile localstack --endpoint-url http://localhost:4566 lambda invoke --function-name user-create --cli-binary-format raw-in-base64-out --payload '{"first_name":"fn","last_name":"ln"}' response.json

{
    "StatusCode": 200,
    "LogResult": "",
    "ExecutedVersion": "$LATEST"
}

响应.json

{
    "id": 1640804522226871000,
    "ok": true,
    "req_id": "773348c7-ed62-14de-8232-07a52eca3215"
}