我正在 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 完全支持该功能的多个触发器?
我通过实现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 来处理一种类型的事件。
您可以配置多个事件源来触发一个或多个 Lambda 函数。
但是,在 Go 中,
lambda.Start
调用是阻塞的,因此编写处理多种事件类型的单个函数并不容易。强烈建议您为每个事件源创建一个单独的 Lambda 函数。
惯用的 Go 解决方案是在主包中定义一次函数逻辑,然后编写多个程序来获取源事件并调用你的函数。所以项目布局是:
查看我的样板 Lambda 和 Go 应用程序 示例项目布局和 Makefile。
创建了一个 Golang 库 以简化 Lambda 函数中多种事件类型的处理。
你可以在 Go 中使用 embedding 来解决这个问题:
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
的另一个比较方法实例。