はじめに
S3バケットのオブジェクト一覧を取得する場合は通常awscliを使用して
aws --profile {profile} s3 ls --recursive s3://{bucket}/{prefix}
のような感じで実行すると思います。
オブジェクトが少なければこれで問題ないですが、大量にあると時間がかかります。
実際に特定prefix配下の(1億ほど)オブジェクト一覧を取得する必要があり、awscliだと
数日かかることが見えていたので、Goで実装してどれだけ速くなるか試してみました。
コード
main.go
package main
import (
"flag"
"fmt"
"os"
"time"
"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"
)
var (
argRegion = flag.String("region", "ap-northeast-1", "specify region name")
argProfile = flag.String("profile", "", "specify credential profile name")
argBucket = flag.String("bucket", "", "specify bucket name")
argPrefix = flag.String("prefix", "", "specify object key prefix")
)
func main() {
flag.Parse()
defer func() {
if r := recover(); r != nil {
flag.Usage()
fmt.Println(r)
os.Exit(1)
}
}()
config := aws.Config{Region: argRegion, MaxRetries: aws.Int(10)}
if *argProfile != "" {
creds := credentials.NewSharedCredentials("", *argProfile)
config.Credentials = creds
}
sess := session.New(&config)
svc := s3.New(sess)
params := &s3.ListObjectsV2Input{Bucket: argBucket, Prefix: argPrefix}
jst, _ := time.LoadLocation("Asia/Tokyo")
svc.ListObjectsV2Pages(params,
func(page *s3.ListObjectsV2Output, lastPage bool) bool {
for _, obj := range page.Contents {
fmt.Printf("%s %10d %s\n", obj.LastModified.In(jst).Format("2006-01-02 15:04:05"), *obj.Size, *obj.Key)
}
return *page.IsTruncated
})
}
実行方法
# コンパイル
go build -o s3lsall main.go
# 実行
./s3lsall -profile {profile} -bucket {bucket} -prefix {prefix}
結果表示は、awscli(aws s3 ls
)と同じフォーマットで出力されます
例
2019-01-22 11:46:39 8023 hoge/197352643.json
2019-01-23 11:16:28 5000 hoge/197512582.json
2019-01-23 19:46:02 4995 hoge/197512839.json
性能比較(参考)
t3.smallインスタンスで実行し、10万オブジェクトの一覧取得で比較
使用ツール | 所要時間 | CPU使用率 |
---|---|---|
awscli | 65秒 | 30% |
s3lsall(go実装) | 15秒 | 10% |
まとめ
awscliで時間がかかりそうな大量リソースに対する処理などは、必要な処理に特化した
プログラムをGoでサクッと実装するとよさそうですね(速度/負荷的にも)
Go以外の言語でsdkを使ってプログラムを書いてもいいですが、そのランタイム環境を用意
しないといけないので、ワンバイナリ配布で実行できる、というのもGoのいいところですね!