本文介绍使用 `juju/ratelimit` 库结合令牌桶算法,为 go 编写的 http 文件服务(上传/下载)添加可配置的带宽限速功能,支持精确控制如 1mb/s 的读写速率。
在构建高可用文件传输服务时,不限速的 I/O 可能导致带宽打满、响应延迟升高甚至影响其他请求。Go 标准库本身不提供内置速率限制器,但借助成熟的第三方限速库(如 juju/ratelimit),我们可通过令牌桶(Token Bucket) 算法优雅实现平滑、可控的上传/下载限速。
该算法核心思想是:以恒定速率向“桶”中注入令牌,每次读/写操作需消耗对应字节数的令牌;若令牌不足则阻塞等待,从而自然达成平均速率上限。ratelimit.Bucket 支持毫秒级精度,且线程安全,非常适合 HTTP 并发场景。
对 http.ResponseWriter 的写入进行限速,需包装 http.ResponseWriter 的底层 io.Writer。推荐方式是创建一个限速的 io.Writer 包装器:
func downloadFile(w http.ResponseWriter, r *http.Request) {
f, err := os.Open(`e:\test\test.mpg`)
if err != nil {
http.Error(w, "file not found", http.StatusNotFound)
return
}
defer f.Close()
// 限速:1 MB/s = 1_048_576 bytes/sec
bucket := ratelimit.NewBucketWithRate(1_048_576, 1_048_576)
// 设置响应头
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", `attachment; filename="test.mpg"`)
// 使用限速 Writer 包装 ResponseWriter 的 Write 方法
limitedWriter := ratelimit.Writer(w, bucket)
_, err = io.Copy(limitedWriter, f)
if err != nil && err != io.ErrClosedPipe {
log.Printf("download error: %v", err)
}
}⚠️ 注意:io.ErrClosedPipe 是客户端主动断连的常见错误,建议忽略以避免日志噪音。
对 http.Request.Body 或 multipart.File 的读取限速,只需用 ratelimit.Reader 包装原始 io.Reader:
func uploadFile(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(32 << 20) // 32MB 内存缓冲
file, _, err :
= r.FormFile("file")
if err != nil {
http.Error(w, "invalid file field", http.StatusBadRequest)
return
}
defer file.Close()
os.MkdirAll(`e:\test`, 0755)
out, err := os.Create(`e:\test\test.mpg`)
if err != nil {
http.Error(w, "failed to create file", http.StatusInternalServerError)
return
}
defer out.Close()
// 限速:1 MB/s(可替换为配置项)
bucket := ratelimit.NewBucketWithRate(1_048_576, 1_048_576)
limitedReader := ratelimit.Reader(file, bucket)
_, err = io.Copy(out, limitedReader)
if err != nil {
http.Error(w, "upload failed: "+err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("upload success"))
}通过上述方式,你无需修改业务逻辑主干,仅需两行包装代码即可为任意 io.Reader/io.Writer 添加精准、低开销的速率控制——让大文件传输更可控、更公平、更健壮。
# go
# app
# 字节
# usb
# ai
# stream
# 内存占用
# 标准库
# Token
# 线程
# map
# 并发
# 算法
# http
# prometheus
# 令牌
# 上传
# 服务端
# 大文件
# 设为
# 可通过
# 第三方
# 可为
# 多用户
# 创建一个
相关文章:
大连 网站制作,大连天途有线官网?
为什么Go需要go mod文件_Go go mod文件作用说明
网站建设制作需要多少钱费用,自己做一个网站要多少钱,模板一般多少钱?
建站之星代理平台如何选择最佳方案?
高性价比服务器租赁——企业级配置与24小时运维服务
成都品牌网站制作公司,成都营业执照年报网上怎么办理?
宝塔新建站点为何无法访问?如何排查?
如何高效完成自助建站业务培训?
青浦网站制作公司有哪些,苹果官网发货地是哪里?
深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?
如何高效利用200m空间完成建站?
制作网站的公司有哪些,做一个公司网站要多少钱?
贸易公司网站制作流程,出口贸易网站设计怎么做?
网站制作培训多少钱一个月,网站优化seo培训课程有哪些?
学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?
网站制作与设计教程,如何制作一个企业网站,建设网站的基本步骤有哪些?
如何选择高效响应式自助建站源码系统?
如何解决ASP生成WAP建站中文乱码问题?
高防服务器如何保障网站安全无虞?
制作企业网站建设方案,怎样建设一个公司网站?
如何自定义建站之星模板颜色并下载新样式?
如何通过宝塔面板实现本地网站访问?
c++23 std::expected怎么用 c++优雅处理函数错误返回【详解】
网站制作难吗安全吗,做一个网站需要多久时间?
清除minerd进程的简单方法
免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?
网站设计制作公司地址,网站建设比较好的公司都有哪些?
头像制作网站在线制作软件,dw网页背景图像怎么设置?
如何在香港服务器上快速搭建免备案网站?
打鱼网站制作软件,波克捕鱼官方号怎么注册?
如何设计高效校园网站?
三星网站视频制作教程下载,三星w23网页如何全屏?
网站网页制作电话怎么打,怎样安装和使用钉钉软件免费打电话?
建站之星IIS配置教程:代码生成技巧与站点搭建指南
常州企业建站如何选择最佳模板?
完全自定义免费建站平台:主题模板在线生成一站式服务
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
C++用Dijkstra(迪杰斯特拉)算法求最短路径
logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?
保定网站制作方案定制,保定招聘的渠道有哪些?找工作的人一般都去哪里看招聘信息?
临沂网站制作公司有哪些,临沂第四中学官网?
建站之星上传入口如何快速找到?
如何在新浪SAE免费搭建个人博客?
定制建站如何定义?其核心优势是什么?
如何选择适合PHP云建站的开源框架?
如何用低价快速搭建高质量网站?
如何在景安云服务器上绑定域名并配置虚拟主机?
网站制作模板下载什么软件,ppt模板免费下载网站?
php条件判断怎么写_ifelse和switchcase的使用区别【对比】
小程序网站制作需要准备什么资料,如何制作小程序?
*请认真填写需求信息,我们会在24小时内与您取得联系。