golang複数のファイルを同時にダウンロード
5588 ワード
背景の説明
分散ファイルシステムがあると仮定すると、そのシステムからローカルマシンにファイルの一部を同時にダウンロードする必要があります.このファイルシステムのノードipの一部と、ダウンロードするファイルfile IDのリストが知られており、これらの情報によってダウンロードアドレスをつなぐことができます.ノードipリストがxx_に保存されますnode.txt、ダウンロードするfile IDはxx_に保存しますfileID.txtで.
コードの例
package main
import (
"bufio"
"flag"
"fmt"
"io"
"math/rand"
"net/http"
"os"
"time"
)
var (
clustername = flag.String("clustername", "c1", "download clustername")
)
//
func ReadLines(fpath string) []string {
fd, err := os.Open(fpath)
if err != nil {
panic(err)
}
defer fd.Close()
var lines []string
scanner := bufio.NewScanner(fd)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, err)
}
return lines
}
//
func Download(clustername string, node string, fileID string) string {
nt := time.Now().Format("2006-01-02 15:04:05")
fmt.Printf("[%s]To download %s
", nt, fileID)
url := fmt.Sprintf("http://%s/file/%s", node, fileID)
fpath := fmt.Sprintf("/yourpath/download/%s_%s", clustername, fileID)
newFile, err := os.Create(fpath)
if err != nil {
fmt.Println(err.Error())
return "process failed for " + fileID
}
defer newFile.Close()
client := http.Client{Timeout: 900 * time.Second}
resp, err := client.Get(url)
defer resp.Body.Close()
_, err = io.Copy(newFile, resp.Body)
if err != nil {
fmt.Println(err.Error())
}
return fileID
}
func main() {
flag.Parse()
// ip
nodelist := ReadLines(fmt.Sprintf("%s_node.txt", *clustername))
if len(nodelist) == 0 {
return
}
// ID
fileIDlist := ReadLines(fmt.Sprintf("%s_fileID.txt", *clustername))
if len(fileIDlist) == 0 {
return
}
ch := make(chan string)
// goroutine
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for _, fileID := range fileIDlist {
node := nodelist[r.Intn(len(nodelist))]
go func(node, fileID string) {
ch // ,
timeout := time.After(900 * time.Second)
for idx := 0; idx < len(fileIDlist); idx++ {
select {
case res := "2006-01-02 15:04:05")
fmt.Printf("[%s]Finish download %s
", nt, res)
case "Timeout...")
break
}
}
}
小結
ダウンロード時にデフォルトのhttp Clientが使用されず、タイムアウト時間が指定されています.ファイルをダウンロードするときにシステムコールが呼び出され、goroutineが停止します.ダウンロードファイルが完了すると、保留中のgoroutineが呼び出され、このgoroutineは後のコードを実行した後に終了します.グローバルタイムアウト制御、タイムアウト後メインスレッドが終了します.