Go 基于令牌桶的限流器实现
来源:脚本之家
2023-01-07 11:48:50
0浏览
收藏
本篇文章向大家介绍《Go 基于令牌桶的限流器实现》,主要包括令牌桶、限流器,具有一定的参考价值,需要的朋友可以参考一下。
简介
如果一般流量过大,下游系统反应不过来,这个时候就需要限流了,其实和上地铁是一样的,就是减慢上游访问下游的速度。
限制访问服务的频次或者频率,防止服务过载,被刷爆等。
Golang 官方扩展包 time(golang.org/x/time/rate) 中,提供了一个基于令牌桶等限流器实现。
原理概述
- 令牌:每次拿到令牌,才可访问
- 桶 ,桶的最大容量是固定的,以固定的频率向桶内增加令牌,直至加满
- 每个请求消耗一个令牌。
- 限流器初始化的时候,令牌桶一般是满的。
具体使用
package limiter
import (
"fmt"
"testing"
"time"
"golang.org/x/time/rate"
)
func TestLimter(t *testing.T) {
limiter := rate.NewLimiter(rate.Every(time.Millisecond*31), 2)
//time.Sleep(time.Second)
for i := 0; i
<blockquote>
<p>执行结果:<br>
=== RUN TestLimter<br>
true 2<br>
true 2<br>
true 2<br>
false 2<br>
true 2<br>
true 2<br>
false 2<br>
true 2<br>
true 2<br>
false 2<br>
--- PASS: TestLimter (0.21s)</p>
</blockquote>
<p>通过执行结果可以看到, 令牌桶开始是2个满的,由于令牌的间隔比请求的间隔多了11ms(31-20), 所以每两个请求会失败一次。<br></p>
<h2>具体实现原理<br></h2>
<p>先看下限流器的创建方法: NewLimiter<br></p>
<pre class="brush:plain;">
func NewLimiter(r Limit, b int) *Limiter {
return &Limiter{
limit: r,
burst: b,
}
}
查看限流器数据结构 Limiter
// The methods AllowN, ReserveN, and WaitN consume n tokens.
type Limiter struct {
mu sync.Mutex
limit Limit
burst int
tokens float64
// last is the last time the limiter's tokens field was updated
last time.Time
// lastEvent is the latest time of a rate-limited event (past or future)
lastEvent time.Time
}
- burst 表示了桶的大小
- limit 表示放入桶的频率
- tokens 表示剩余令牌个数
- last 最近取走 token 的时间
- lastEvent 最近限流事件的时间
当令牌桶发放后,会保留在 Reservation 对象中, 定义如下, Reservation 对象,描述了一个达到 timeToAct 时间后,可以获取到的令牌的数量 tokens 数。
type Reservation struct {
ok bool // 是否满足条件分配到了tokens
lim *Limiter // 发送令牌的限流器
tokens int // tokens 的数量
timeToAct time.Time // 满足令牌发放的时间
limit Limit // 令牌发放速度
}
限流器如何限流
官方提供的限流器有阻塞等待, 也有直接判断方式的, 还有提供维护预留式等。
如何实现限流的代码,在 reserveN 中。
使用时,每次都调用了 Allow() 方法
// Allow is shorthand for AllowN(time.Now(), 1).
func (lim *Limiter) Allow() bool {
return lim.AllowN(time.Now(), 1)
}
// AllowN reports whether n events may happen at time now.
// Use this method if you intend to drop / skip events that exceed the rate limit.
// Otherwise use Reserve or Wait.
func (lim *Limiter) AllowN(now time.Time, n int) bool {
return lim.reserveN(now, n, 0).ok
}
继续查看 reserverN 算法
方法说明:
- 三个参数: now, n, maxFutureReserve
- 在 now 时间需要拿到 n 个令牌,最多等待的时间为 maxFutureReserve
- 结果将返回一个预留令牌的对象 Reservation
// maxFutureReserve specifies the maximum reservation wait duration allowed.
// reserveN returns Reservation, not *Reservation, to avoid allocation in AllowN and WaitN.
func (lim *Limiter) reserveN(now time.Time, n int, maxFutureReserve time.Duration) Reservation {
lim.mu.Lock()
// 首先判断是否放入频次是否为无穷大,如果为无穷大,说明暂时不限流
if lim.limit == Inf {
lim.mu.Unlock()
return Reservation{
ok: true,
lim: lim,
tokens: n,
timeToAct: now,
}
}
// 拿到截止 now 时间时,可以获取的令牌 tokens 数量,上一次拿走令牌的时间是last
now, last, tokens := lim.advance(now)
// Calculate the remaining number of tokens resulting from the request.
// 更新 tokens数量,把需要拿走的去掉
tokens -= float64(n)
// Calculate the wait duration
// 如果 tokens 数量为负数,说明需要等待,计算等待时间 WaitDuration
var waitDuration time.Duration
if tokens
<p>从实现上看, limiter 并不是每隔一段时间更新当前桶的数量,而是记录了上次访问时和当前桶中令牌的数量,当再次访问时,通过上次访问时间计算出当前令牌的数量,决定是否可以发放令牌。</p>
<p>今天带大家了解了令牌桶、限流器的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~</p> 版本声明
本文转载于:脚本之家 如有侵犯,请联系study_golang@163.com删除
详解Golang语言HTTP客户端实践
- 上一篇
- 详解Golang语言HTTP客户端实践
- 下一篇
- Golang语言如何高效拼接字符串详解
查看更多
最新文章
-
- Golang · Go教程 | 16分钟前 |
- Golang接口多态实现全解析
- 241浏览 收藏
-
- Golang · Go教程 | 25分钟前 |
- GolangHTTP优化与中间件组合技巧
- 365浏览 收藏
-
- Golang · Go教程 | 26分钟前 |
- Golang模块版本管理与升级技巧
- 247浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Golang实现WebSocket聊天教程
- 241浏览 收藏
-
- Golang · Go教程 | 1小时前 | 日志文件管理 lumberjack Golang日志滚动 log库 zap库
- Golang日志滚动实现全解析
- 467浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Nixflakes管理Golang依赖实现稳定构建
- 500浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Golang数组切片传参方法解析
- 249浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Golang并发队列实现与使用技巧
- 132浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go调用DLL传递数组指针方法解析
- 450浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- MacGo安装ld链接器失败解决方法
- 209浏览 收藏
查看更多
课程推荐
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
查看更多
AI推荐
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3161次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3374次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3402次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4505次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3783次使用
查看更多
相关文章
-
- golang高并发系统限流策略漏桶和令牌桶算法源码剖析
- 2022-12-31 179浏览
-
- Go实现分布式系统高可用限流器实战
- 2022-12-28 317浏览
-
- Go官方限流器的用法详解
- 2023-01-09 439浏览
-
- Golang模拟令牌桶进行对访问的限流方式
- 2023-01-27 217浏览
-
- golang简易令牌桶算法实现代码
- 2022-12-27 285浏览

