go routines 在下载大文件时挂起

标签 go

我正在尝试编写一个应用程序来下载一系列图像。

  • 130 张 116kb 图片(作品)
  • 50 张 500kb 图片(作品)
  • 130 张 500kb 的图片(最终挂起)
  • 230 张 116kb 图片(最终挂起)

go版本go1.9.2 darwin/amd64

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "os"
    "sync"
)

func main() {

    var urls []string

    // var smallImage = "https://s3.amazonaws.com/golangplayground/116kb.jpeg" //116kb
    var largeImage = "https://s3.amazonaws.com/golangplayground/SampleJPGImage_500kbmb.jpg" //500kb
    for i := 0; i < 130; i++ {
        urls = append(urls, largeImage)
    }

    var wg sync.WaitGroup
    wg.Add(len(urls))
    var inc = 0
    for _, val := range urls {
        inc += 1
        go saveResourceFromURLToDisk(val, "./foo", &wg, inc)
    }
    wg.Wait()
    fmt.Println("done.")
}

func saveResourceFromURLToDisk(url string, writeTo string, wg *sync.WaitGroup, inc int) error {
    defer wg.Done()

    response, err := http.Get(url)
    if err != nil {
        log.Fatal(err)
        return err
    }
    defer response.Body.Close()

    localPath := fmt.Sprintf("%s/%d", writeTo, inc)
    file, err := os.Create(localPath)
    if err != nil {
        log.Fatal(err)
        return err
    }
    defer file.Close()

    _, err = io.Copy(file, response.Body)
    if err != nil {
        log.Fatal(err)
        return err
    }

    fmt.Println(localPath)
    return nil
}

最佳答案

这可能是网络问题。 Web 浏览器限制打开同一服务器的 session 数是有原因的。

如果同时打开一堆 TCP session ,几乎所有 session 都会丢失数据包。然后他们都会尝试在大约同一时间重试,丢失更多的数据包。这只是一大堆损失。

在打开每个 GET 请求之间设置一个小的延迟,或者将您自己限制为从同一服务器同时下载 4 到 8 个。

关于go routines 在下载大文件时挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48009804/

相关文章:

mysql - 全选在 golaong gorm 中不起作用

go找不到sdl

multithreading - golang可以启动多线程来处理网络IO吗

go - 我如何在 golang 的 UDP 服务器上获取客户端 ip 地址?

go - 如何通过锁定在 Go 中实现线程安全的映射包装器?

Vb.net 到 golang AES

go - 如何从 Gin 的前端获取数据?

c - 编写伪装成 TTY 的程序

go - 如何在 switch 语句中先声明结构然后再初始化它?

go - 为什么我不能在 go 中将 `func() []int` 作为 `func() []interface{}` 传递?