问题 如何限制golang中服务器的上传和下载速度?


如何限制golang中服务器的上传和下载速度?

我正在写一个golang服务器,允许用户上传和下载文件。文件很大,大约1GB字节。我想将上传和下载速度限制为(例如)1MB / s(当然可配置)。

下面是我的上传代码:

func uploadFile(w http.ResponseWriter, r *http.Request) {
    file, _, err := r.FormFile("file")

    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }

    defer file.Close()

    os.MkdirAll(`e:\test`, os.ModePerm)
    out, err := os.Create(`e:\test\test.mpg`)
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }

    defer out.Close()

    _, err = io.Copy(out, file)
    if err != nil {
        http.Error(w, err.Error(), 500)
    }
}

7890
2017-11-28 11:22


起源



答案:


有一个 令牌桶 有助于实现这种速率限制的算法。我找到了一个示例实现,您可以使用它: https://github.com/juju/ratelimit

package main

import (
    "bytes"
    "fmt"
    "io"
    "time"

    "github.com/juju/ratelimit"
)

func main() {
    // Source holding 1MB
    src := bytes.NewReader(make([]byte, 1024*1024))
    // Destination
    dst := &bytes.Buffer{}

    // Bucket adding 100KB every second, holding max 100KB
    bucket := ratelimit.NewBucketWithRate(100*1024, 100*1024)

    start := time.Now()

    // Copy source to destination, but wrap our reader with rate limited one
    io.Copy(dst, ratelimit.Reader(src, bucket))

    fmt.Printf("Copied %d bytes in %s\n", dst.Len(), time.Since(start))
}

运行后,输出为:

Copied 1048576 bytes in 9.239607694s

您可以使用不同的存储桶实现来提供所需的行为。在您的代码中,在设置了正确的令牌桶之后,您将调用:

_, err = io.Copy(out, ratelimit.Reader(file, bucket))

14
2017-11-28 13:51



这可以限制文件写入速度,但我看到表单任务管理器网络保持高速。我想限制网络数据传输速度。谢谢 - waitwone
这是我的问题。我应该使用r.MultipartReader()和reader.NextPart()而不是r.FromFile(),因为r.FromFile()会将数据保存在系统临时文件中。谢谢! - waitwone


答案:


有一个 令牌桶 有助于实现这种速率限制的算法。我找到了一个示例实现,您可以使用它: https://github.com/juju/ratelimit

package main

import (
    "bytes"
    "fmt"
    "io"
    "time"

    "github.com/juju/ratelimit"
)

func main() {
    // Source holding 1MB
    src := bytes.NewReader(make([]byte, 1024*1024))
    // Destination
    dst := &bytes.Buffer{}

    // Bucket adding 100KB every second, holding max 100KB
    bucket := ratelimit.NewBucketWithRate(100*1024, 100*1024)

    start := time.Now()

    // Copy source to destination, but wrap our reader with rate limited one
    io.Copy(dst, ratelimit.Reader(src, bucket))

    fmt.Printf("Copied %d bytes in %s\n", dst.Len(), time.Since(start))
}

运行后,输出为:

Copied 1048576 bytes in 9.239607694s

您可以使用不同的存储桶实现来提供所需的行为。在您的代码中,在设置了正确的令牌桶之后,您将调用:

_, err = io.Copy(out, ratelimit.Reader(file, bucket))

14
2017-11-28 13:51



这可以限制文件写入速度,但我看到表单任务管理器网络保持高速。我想限制网络数据传输速度。谢谢 - waitwone
这是我的问题。我应该使用r.MultipartReader()和reader.NextPart()而不是r.FromFile(),因为r.FromFile()会将数据保存在系统临时文件中。谢谢! - waitwone


你可以查看一下它的实现 PuerkitoBio/throttled, 呈现 在这篇文章中

throttled,一个Go包,它实现了各种策略来控制对HTTP处理程序的访问。
  开箱即用,它支持 请求的速率限制,请求的恒定间隔流和授予或拒绝访问的内存使用阈值,但它也提供了扩展其功能的机制。

速率限制并不完全符合您的需求,但可以提供一个好主意 实现类似的功能


2
2017-11-28 11:26