利用 aws lambda 来实时同步用户上传到 s3 bucket 的 object 到 bos bucket。
aws lambda 是一项计算服务,无需预配置或管理服务器即可运行代码,你可以通过配置 aws lambda的触发器来执行你上传的函数代码。因此,我们可以利用 aws lambda 来实时同步用户上传到 s3 bucket 的 object 到 bos bucket。
您可以登陆 aws,使用 lambda 设置针对文件上传的监听规则,并根据该操作触发文件同步到 bos 的操作。
登录aws 控制台,进入,点击“创建函数”
从头开始创建函数,该示例中运行语言选择go 1.x(后续示例lambda程序也是go程序,用户可以选择自己擅长的语言来实现lambda函数),角色选择从模板创建新角色即可
配置lambda函数desiger、函数代码、并发、内存分配、超时时间,环境变量等,按需配置
基本配置:按需配置,例如你的代码执行需要的内存大小,超时时间、环境变量
注意事项
- 超时时间建议填1分钟以上,lambda函数从s3下载文件,再上传到bos耗时与object大小有关,有时会比较长,按实际情况设置即可;
- lambda函数保存object到磁盘,只能选择/tmp/目录,其他目录没有写权限;
- 内存配置与函数运行时需要的内存大小有关,按实际需要设置即可。
上传lambda代码:上传代码必须为zip格式,处理程序填写go文件的文件名
配置触发器:我们选择s3触发器,进一步选择需要监听的s3存储桶,还能通过object前后缀缩小监听事件范围;添加之后会看到触发器内容为:存储桶: s3/bucket-name 事件类型: objectcreated
保存配置,用户每次上传object到s3 bucket,就会执行上传的go lambda代码,同步该object到bos;进入控制台可以查看程序执行的日志
库环境准备:参考aws s3 golang sdk和bos golang sdk使用教程
go get -u github.com/aws/aws-sdk-go/...
go get github.com/aws/aws-lambda-go/lambda
go get github.com/baidubce/bce-sdk-go
代码保存在s32bos.go文件中,编译成二进制文件之后压缩成zip文件上传,命令如下
goos=linux goarch=amd64 go build -o s32bos s32bos.go
zip s32bos.zip s32bos
s32bos.go代码:
package main
import (
"context"
"fmt"
"os"
)
import (
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/baidubce/bce-sdk-go/services/bos"
)
var (
s3_region = "ap-northeast-1"
s3_ak = "akiaj*****lwgryaulyta"
s3_sk = "abzri****rqhre8vzvuesvqmwxcsopimj7"
bos_ak = "388e4e0b*****cfff3cbecb5"
bos_sk = "2db53e648c53456e***5b7d378"
bos_endpoint = "http://bj.bcebos.com"
bos_bucket = "bucket-name"
)
func downloadfroms3(bucket string, object string) {
file, err := os.create("/tmp/" object)
if err != nil {
fmt.printf("unable to open file, err %v", err)
}
defer file.close()
// init s3 downloader
sess, err := session.newsession(&aws.config{
region: aws.string(s3_region),
credentials: credentials.newstaticcredentials(s3_ak, s3_sk, ""),
})
downloader := s3manager.newdownloader(sess)
numbytes, err := downloader.download(file,
&s3.getobjectinput{
bucket: aws.string(bucket),
key: aws.string(object),
})
if err != nil {
fmt.printf("unable to download object %s, size %d, err %v", object, numbytes, err)
}
fmt.println("download from s3 success")
}
func upload2bos(bucket string, object string) {
bosclient, err := bos.newclient(bos_ak, bos_sk, bos_endpoint)
if err != nil {
fmt.printf("create bos client err %v", err)
return
}
etag, err := bosclient.putobjectfromfile(bucket, object, "/tmp/" object, nil)
if err != nil {
fmt.printf("put object to bos err %v", err)
return
}
fmt.printf("upload2bos success etag: %s", etag)
}
func handlelambdaevent(ctx context.context, s3event events.s3event) {
fmt.println("start to handle lambda event")
for _, record := range s3event.records {
s3 := record.s3
fmt.printf("[%s - %s] bucket = %s, object = %s \n", record.eventsource, record.eventtime, s3.bucket.name, s3.object.key)
downloadfroms3(s3.bucket.name, s3.object.key)
upload2bos(bos_bucket, s3.object.key)
}
fmt.println("handle lambda event success")
}
func main() {
lambda.start(handlelambdaevent)
}