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は後のコードを実行した後に終了します.グローバルタイムアウト制御、タイムアウト後メインスレッドが終了します.