http.Get() を使用して Nginx サーバーからファイルをフェッチする関数を作成しました (これは、テスト用にファイルをフェッチするホストと同じホストにあります)。コードは次のようになります。
res,err := http.Get(addr) // addr is the file address on Nginx server
defer res.Body.Close()
for {
v := &vFile{path,0} // path is the file path to write
bv :=bufio.NewWriterSize(v,1024*1024) // Write 1MB each time
_, err:= io.Copy(bv,res.Body)
if err == nil { err = bv.Flush() }
}
vFile と次のように定義された Write 関数を使用
type vFile struct {
path string
cur int64
}
func (wtr *vFile) Write(buf []byte) {
var f *os.File
if wtr.cur == 0 { f,wtr.err = os.Create(wtr.path) }
else { f,wtr.err = os.OpenFile(wtr.path,os.O_RDWR|os.O_APPEND,0666) }
_, err := f.WriteAt(buf,twr.path)
}
ただし、同時実行数が多い状況 (たとえば、同時実行数が 500) では、多数のファイルが完全にはフェッチされず、Nginx ログでは、ファイル長が正しくないのに HTTP 応答が 200 になります。
"GET /videos/4b42d6e8e138233c7eb62939.mp4 HTTP/1.1" 200 37863424 "-" "Go 1.1 package http" "-"
ファイルのサイズは 75273523 バイトですが、フェッチされるのは 37863424 バイトのみです。サイズを 1MB から 32KB に変更すると、状況はかなり改善される可能性がありますが、まだ完全ではないファイルがいくつかあります。では、コードのどこが間違っているのでしょうか?