全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

如何在Golang中实现请求限流_使用Channel和计数器控制并发

Go中可用带缓冲channel实现令牌桶限流:初始化容量为maxTokens的channel并预填满,请求时select尝试取令牌,成功则处理,失败则拒绝;后台goroutine定期补充令牌。

在 Go 中实现请求限流,用 Channel 和计数器是最轻量、最易理解的方式之一。核心思路是:用一个带缓冲的 channel 当作“令牌桶”,每次请求先尝试获取一个令牌(从 channel 取值),成功则处理请求,失败则拒绝;后台 goroutine 定期往 channel 里放令牌(恢复配额)。配合简单计数器还能做更细粒度的窗口限流(比如每秒最多 N 次)。

用 buffered Channel 实现令牌桶(Token Bucket)

这是最典型的 channel 限流方式,适合控制平均速率和应对突发流量。

  • 初始化一个容量为 maxTokens 的 channel,初始填满
  • 每次请求执行 select { case 尝试非阻塞取令牌
  • 另起 goroutine 每隔 interval 时间向 channel 放一个令牌(不超过容量)

示例代码片段:

func NewTokenBucket(maxTokens int, interval time.Duration) *TokenBucket {
    ch := make(chan struct{}, maxTokens)
    for i := 0; i < maxTokens; i++ {
        ch <- struct{}{}
    }
    tb := &TokenBucket{ch: ch}
    go func() {
        ticker := time.NewTicker(interval)
        defer ticker.Stop()
        for range ticker.C {
            select {
            case ch <- struct{}{}:
            default: // 已满,不覆盖
            }
        }
    }()
    return tb
}

func (tb *TokenBucket) Allow() bool { select { case <-tb.ch: return true default: return false } }

用原子计数器 + 时间窗口实现滑动窗口限流

如果需要严格限制“最近 1 秒内最多 100 次”,单纯 channel 不够精确,这时用 sync/atomic 配合时间戳分片更合适。

  • 把 1 秒切分成多个 slot(如 10 个 100ms slot),每个 slot 记录该时间段请求数
  • atomic.Int64 存储当前总请求数,同时定期清理过期 slot
  • 或更简单:只维护当前窗口开始时间 + 计数器,超时就重置(适合低精度场景)

简易版(固定窗口):

type FixedWindowLimiter struct {
    mu        sync.RWMutex
    count     int64
    lastReset time.Time
    limit     int64
    window    time.Duration
}

func (l *FixedWindowLimiter) Allow() bool { l.mu.Lock() defer l.mu.Unlock()

now := time.Now()
if now.Sub(l.lastReset) >= l.window {
    l.count = 0
    l.lastReset = now
}

if l.count >= l.limit {
    return false
}
l.count++
return true

}

组合使用:Channel 控制并发数 + 计数器控制频次

真实服务常需双重防护:既不让瞬时并发打爆 CPU(channel 控制 goroutine 数量),也不让单 IP 狂刷接口(计数器按 key 限频)。

  • 用 channel 控制全局最大并发处理数(类似 http.Server 的 MaxConns
  • 对每个 client IP 或 user ID 维护独立的计数器(可用 map + sync.Map + 定时清理)
  • 中间件中先检查 IP 频率,再尝试获取全局处理许可

注意点:

  • 避免 map 并发写,用 sync.Map 或加锁
  • 计数器要带 TTL,否则内存泄漏;可用 expirable.Map 或自己定时扫描
  • channel 方式天然支持超时:select { case

生产建议:优先用成熟库,而非手写

虽然手写能帮你深入理解,但线上建议用经过压测的库:

  • uber-go/ratelimit:基于 token bucket,高性能,无锁
  • juju/ratelimit:经典 leaky bucket 实现
  • gin-contrib/limiter:Gin 生态集成方便

它们已处理好时钟漂移、高并发竞争、内存回收等细节,自研容易踩坑。

基本上就这些。channel 适合快速控并发,计数器适合按维度控频次,两者不冲突,可以叠加用。关键不是选哪种,而是清楚你要防的是什么——是雪崩?是爬虫?还是资源耗尽?想明白这点,方案自然就清晰了。


# go  # golang  # red  # select  # Token  # 并发  # channel  # 令牌  # 最多  # 的是  # 这是  # 切分  # 多个  # 你要  # 帮你  # 线上  # 不超过 


相关文章: 如何挑选优质建站一级代理提升网站排名?  如何快速生成橙子建站落地页链接?  制作销售网站教学视频,销售网站有哪些?  北京建设网站制作公司,北京古代建筑博物馆预约官网?  建站之星CMS五站合一模板配置与SEO优化指南  动图在线制作网站有哪些,滑动动图图集怎么做?  如何通过免费商城建站系统源码自定义网站主题与功能?  建站之星后台密码遗忘?如何快速找回?  北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?  c# 在高并发场景下,委托和接口调用的性能对比  教学网站制作软件,学习*后期制作的网站有哪些?  建站之星如何开启自定义404页面避免用户流失?  装修招标网站设计制作流程,装修招标流程?  如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?  如何彻底卸载建站之星软件?  一键网站制作软件,义乌购一件代发流程?  如何通过.red域名打造高辨识度品牌网站?  ui设计制作网站有哪些,手机UI设计网址吗?  济南企业网站制作公司,济南社保单位网上缴费步骤?  h5网站制作工具有哪些,h5页面制作工具有哪些?  矢量图网站制作软件,用千图网的一张矢量图做公司app首页,该网站并未说明版权等问题,这样做算不算侵权?应该如何解决?  建站主机数据库如何配置才能提升网站性能?  网站制作培训多少钱一个月,网站优化seo培训课程有哪些?  大同网页,大同瑞慈医院官网?  上海制作企业网站有哪些,上海有哪些网站可以让企业免费发布招聘信息?  购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?  代刷网站制作软件,别人代刷火车票靠谱吗?  如何在建站之星绑定自定义域名?  C++如何编写函数模板?(泛型编程入门)  如何快速辨别茅台真假?关键步骤解析  招商网站制作流程,网站招商广告语?  建站主机默认首页配置指南:核心功能与访问路径优化  网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?  如何在七牛云存储上搭建网站并设置自定义域名?  Swift中swift中的switch 语句  车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?  GML (Geography Markup Language)是什么,它如何用XML来表示地理空间信息?  猪八戒网站制作视频,开发一个猪八戒网站,大约需要多少?或者自己请程序员,需要什么程序员,多少程序员能完成?  济南网站建设制作公司,室内设计网站一般都有哪些功能?  简历在线制作网站免费版,如何创建个人简历?  如何在Golang中使用encoding/gob序列化对象_存储和传输数据  网站图片在线制作软件,怎么在图片上做链接?  ,在苏州找工作,上哪个网站比较好?  专业公司网站制作公司,用什么语言做企业网站比较好?  制作网站哪家好,cc、.co、.cm哪个域名更适合做网站?  专业网站制作企业网站,如何制作一个企业网站,建设网站的基本步骤有哪些?  宝塔面板创建网站无法访问?如何快速排查修复?  如何在Golang中引入测试模块_Golang测试包导入与使用实践  如何在西部数码注册域名并快速搭建网站?  佛山网站制作系统,佛山企业变更地址网上办理步骤? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。