如何限制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)
}
}
答案 0 :(得分:16)
有token bucket算法可以帮助实现这样的速率限制。我找到了一个示例实现,您可以使用它: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))
答案 1 :(得分:2)
您可以查看PuerkitoBio/throttled
的实施情况,提交in this article:
throttled
,一个Go包,它实现了各种策略来控制对HTTP处理程序的访问。
开箱即用,它支持请求的速率限制,请求的恒定间隔流和授予或拒绝访问的内存使用阈值,但它还提供了扩展其功能的机制。
速率限制并不完全符合您的需求,但可以为implementing a similar feature提供一个好主意。