13

我正在 Golang 中构建一个 AWS Lambda 函数,它将内容从 n 个 S3 存储桶复制到 m 个。需要支持 S3 触发器以及从存储所有源 S3 存储桶更改的 SQS 获取数据。代码可以在这里找到:https ://github.com/maknahar/s3copy

我试过以下:

func main() {
    lambda.Start(ProcessIncomingS3Events)
    lambda.Start(ProcessIncomingEvents)
}

func ProcessIncomingS3Events(event events.S3Event) error {
    ...
    log.Println("Got S3 Event")
    return processS3Trigger(config, event)
}

func ProcessIncomingEvents() error {
    ...
    log.Println("Defaulting to SQS")
    return processSQSMessage(config)
}

在这种情况下,ProcessIncomingS3Events每次都会触发第一个事件。

我也尝试过

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

func ProcessIncomingEvents(event interface{}) error {
    ...
    switch request := event.(type) {
    case events.S3Event:
        log.Println("Got S3 Event")
        return processS3Trigger(config, request)

    case types.Nil:
        log.Println("Defaulting to SQS")
        return processSQSMessage(config)

    default:
        log.Println("Could not find the event type")

    }

    return nil
}

在这种情况下,Lambda 无法检测到类型并Could not find the event type记录在每个触发器中。

有没有办法通过 AWS SDK 支持多个触发器的功能?

4

4 回答 4

6

我通过实现aws Handler接口实现了监听多个事件,它定义了一种方法

Invoke(ctx context.Context, payload []byte) ([]byte, error)

我实现了一个多事件处理程序如下

type Handler struct {
//add global variables or context information that your handler may need
}

func (h Handler) Invoke(ctx context.Context, data []byte) ([]byte, error) {
  //for demonstration purposes, not the best way to handle
  apiGatewayEvent := new(events.APIGatewayProxyRequest)
  if err := json.Unmarshal(data, apiGatewayEvent); err != nil {
    log.Println("Not a api gateway event")
  }
  snsEvent := new(events.SNSEvent)
  if err := json.Unmarshal(data, snsEvent); err != nil {
    log.Println("Not a sns event")
  }
  return nil, nil
}

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

如您所见,您可以获取任何事件的原始字节并根据需要处理它们,让您可以使用相同的 lambda 监听任何 aws 事件。但是,在使用这种方法之前要仔细考虑,因为如上所述,lambda 最好只处理一种类型的事件

希望这可以帮助。

于 2018-09-29T22:08:38.937 回答
1

您可以配置多个事件源来触发一个或多个 Lambda 函数。

但是,在 Go 中,lambda.Start调用是阻塞的,因此编写一个处理多种事件类型的函数并不容易。强烈建议您为每个事件源创建一个单独的 Lambda 函数。

惯用的 Go 解决方案是在主包中定义一次您的函数逻辑,然后编写多个程序来获取源事件并调用您的函数。所以项目布局将是:

  • s3copy/main.go
  • s3copy/handlers/s3/main.go
  • s3copy/handlers/sqs/main.go

有关示例项目布局和 Makefile,请参阅我的样板 Lambda 和 Go 应用程序。

于 2018-03-30T14:42:46.777 回答
0

我不是 GoLang 人。只是猜测正常的编程思维。

在方法一中,您在第一条语句中直接调用 ProcessIncomingS3Events ,因此每次都会调用它。

阅读本文- Lambda 函数处理程序 (Go)

在上面的链接中,作者正在解析事件的名称字段。同样,您可以检查 S3 事件中始终存在的任何字段,例如“eventSource”:“aws:s3”(S3 事件结构见此处

如果存在则 S3 事件否则其他。或者您也可以检查 SQS 事件的字段。

HIH

于 2018-03-27T16:08:24.553 回答
0

你可以在 Go 中使用嵌入来解决这个问题

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

type Event struct {
    events.SQSEvent
    events.APIGatewayProxyRequest
    //other event type
}

type Response struct {
    events.SQSEventResponse `json:",omitempty"`
    events.APIGatewayProxyResponse `json:",omitempty"`
   //other response type
}

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

func eventRouter(event Event) (Response, error) {
    var response Response
    switch {
    case reflect.DeepEqual(event.APIGatewayProxyRequest, events.APIGatewayProxyRequest{}):
        response.SQSEventResponse = sqsEventHandler(event.SQSEvent)
    case reflect.DeepEqual(event.SQSEvent, events.SQSEvent{}):
        response.APIGatewayProxyResponse = apiGatewayEventHandler(event.APIGatewayProxyRequest)
  //another case for a event handler
    }
    return response, nil
}


func sqsEventHandler(sqsEvent events.SQSEvent) events.SQSEventResponse {
    //do something with the SQS event 
}

func apiGatewayEventHandler(apiEvent events.APIGatewayProxyRequest) events.APIGatewayProxyResponse {
    //do something with the API Gateway event
}

注意:如果基本事件有一些相同的字段名称,您将需要寻找另一个 DeepEqual 的比较方法实例。

注2:对不起我的英语,来自阿根廷的问候

于 2022-02-14T20:27:43.947 回答