Go语言实现的下载服务速度限制方案
发表时间: 2024-05-21 11:51
如何解决在golang中如何限制服务器上载和下载的速度?
github地址:
github.com/juju/ratelimit
ratelimit 包提供了一个高效的令牌桶实现
package mainimport ("bytes""fmt""io""time""github.com/juju/ratelimit")func main() { // 源容量1MB src := bytes.NewReader(make([]byte, 1024*1024)) // 目的地 dst := &bytes.Buffer{} // Bucket每秒增加100KB,最多可容纳100KB bucket := ratelimit.NewBucketWithRate(100*1024, 100*1024) start := time.Now() // 将源复制到目的地,但用价格有限的一个包装我们的读者 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: 文件下载服务的速率限制
package mainimport ("fmt""io""net/http""os""github.com/juju/ratelimit")// 本案例演示文件服务下载的限流// io.Copy// downloadHandler : 文件下载接口func downloadHandler(w http.ResponseWriter, r *http.Request) { r.ParseForm() filename := r.Form.Get("filename") //获取文件的名称 localPath := "C:/tmp/" + filename // 打开文件 f, err := os.Open(localPath) if err != nil { w.WriteHeader(http.StatusInternalServerError) // 500 return } defer f.Close() //下载响应头设置 w.Header().Set("Content-Type", "application/octect-stream") w.Header().Set("content-disposition", "attachment; filename=\""+filename+"\"") // 下载速度 100KB/s // NewBucketWithRate 返回一个令牌桶, 该桶以每秒速率令牌的速率填充桶, 直至达到给定的最大容量。由于时钟分辨率有限, 在高速率下, 实际速率可能与指定速率相差高达 1%。 // 创建一个令牌桶, 设置每秒速率(rate)、初始容量(capacity)。 bucket := ratelimit.NewBucketWithRate(100*1024, 100*1024) // 单位: 字节 1KB 等于 1024 byte(字节) io.Copy(w, ratelimit.Reader(f, bucket))}/*http://localhost:8080/download?filename=zuoweibiao.png*/func main() { // 静态资源处理 http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static")))) // 动态接口路由设置 http.HandleFunc("/download", downloadHandler) // 监听端口 fmt.Println("文件服务正在启动, 监听端口:8080...") err := http.ListenAndServe(":8080", nil) if err != nil { fmt.Printf("Failed to start server, err:%s", err.Error()) }}
相关的方法解释:
// 指定时间间隔、容量大小的令牌桶、每个tick添加的令牌数 1、 clock的类型是Clockfunc NewBucket(fillInterval time.Duration, capacity int64) *Bucket// 指定时间间隔、容量大小、每个tick添加的令牌数 quantumfunc NewBucketWithQuantum(fillInterval time.Duration, capacity, quantum int64) *Bucket// 创建填充速度为指定速率和容量大小的令牌桶// NewBucketWithRate(0.5, 100) 表示每秒填充50个令牌, fillInterval 时间间隔为1func NewBucketWithRate(rate float64, capacity int64) *Bucket
limiter包
github地址:
github.com/dxvgef/limiter
实例2: 文件下载服务的速率限制
package mainimport ( "log" "net/http" "github.com/dxvgef/limiter")func main() { http.HandleFunc("/", func (resp http.ResponseWriter, req *http.Request) { // 传输demo.mp4文件, 限速每秒100KB if err := limiter.ServeFile(resp, req, "./demo.mp4", 100*1024); err != nil { resp.WriteHeader(500) resp.Write([]byte(err.Error())) } }) if err := http.ListenAndServe(":8080", nil); err != nil { log.Println(err.Error()) return }}