LoginSignup
75

More than 5 years have passed since last update.

golang で S3 に大量ファイルを並列でアップロードする

Last updated at Posted at 2014-09-24

概要

s3関連のコマンドは色々と既存のものがありますが、
javaだったり、rubyだったり、なんだかんだインストールが面倒。
大量のファイルをS3にアップロードするのに随分と時間がかかる。
複数のファイルを並列でアップロードできたらイイなというのと、
golangならインストールも実行ファイル1つだけで済むしなぁ・・・
という思いから、golangを使って「エイや!」で作って
とりあえず、動くものができました。-> https://github.com/masahide/s3cp

golangでAWS APIを使うには

goamzを使えばよさそうです。

しかしgithub上にgoamzのforkが一杯あり、どれが良いのか迷います。
今回は星の数等から github.com/crowdmob/goamz を選択しました。

s3へのアップロード

goamzを使えば簡単です。

https://github.com/golang-samples/goamz/blob/master/s3/simple/main.go
こちらのサンプルが分かりやすいですが、もっと省略して書くと

data := []byte("Hello, Goamz!!")

auth, _ := aws.EnvAuth()
s := s3.New(auth, aws.APNortheast)
bucket := s.Bucket(bucketName)
bucket.Put("path/to/sample.txt", data, "text/plain", s3.Private, s3.Options{})

こんな感じでしょうか。
しかし、このままだと、
メモリ上にファイルを全部読み込むことになるので、少し工夫してPutReaderを使います。

file, _ = os.Open("path/to/sample.txt")
defer file.Close()
fileinfo, _ = file.Stat()
bucket.PutReader("path/to", file, fileinfo.Size(), "application/octet-stream", s3.Private, s3.Options{})

これで、io.Readerを使ってくれるようになるので、メモリにファイルを読み込む必要がありません。

並列化

これに関しては「goroutineを使う」で終わりそうなんですが、
前から興味があった「Advanced Go Concurrency Patterns」に出てくるような「チャンネルのチャンネル」を使った実装に挑戦してみました。
調べてみると、ちょうど良さそうな記事が見つかったので、この実装を真似て、簡単なqueueとworkerを実装しました。

参考の元記事にあるコードほぼそのままなんですが、
queueからworkerにworkを渡すディスパッチャーで goroutineを使っている部分に若干手を加えました。

この部分は、WorkQueueにworkを投げ込まれたら、すぐに無条件でgoroutineを起動することで、WorkQueueを常に空っぽに保つようになっています。
元記事ではgoroutineのコストが安いからこうしているようなことが書かれている(多分)のですが。
このままだと投げ込まれたworkの数だけgoroutineが起動する形になるので、メモリがある限りworkを受け付けてしまい、
最悪メモリ等のリソースが枯渇しそうな気がします。
幸い今回は、WorkQueueが一杯になって「待ち」が発生しても問題がありません。

というわけで、ここのgoroutine化を辞めることで、WorkQueueが一杯になったらWorkerが飽くまで待つようにしました。

追記

WorkQueueとWrokerQueueの残り数をカウントして処理の終了を確認しているのだけど、WorkQueueを受け取ってWorkerQueueを受け取る部分で、一瞬両方空としてカウントしてしまう瞬間が生まれそう?
なので、Goでのパイプラインとキャンセルで実装するのが正しそう。

追記 2014/10/13

Goでのパイプラインとキャンセルをつかった実装に修正しました。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
75