返回顶部
首页 > 资讯 > 后端开发 > GO >Go官方限流器的用法详解
  • 914
分享到

Go官方限流器的用法详解

2024-04-02 19:04:59 914人浏览 安东尼
摘要

目录限流器的内部结构构造限流器使用限流器Wait/WaitNAllow/AllowNReserve/ReserveN动态调整速率和桶大小总结限流器是提升服务稳定性的非常重要的组件,可

限流器是提升服务稳定性的非常重要的组件,可以用来限制请求速率,保护服务,以免服务过载。限流器的实现方法有很多种,常见的限流算法固定窗口、滑动窗口、漏桶、令牌桶

简单来说,令牌桶就是想象有一个固定大小的桶,系统会以恒定速率向桶中放 Token,桶满则暂时不放。在请求比较的少的时候桶可以先"攒"一些Token,应对突发的流量,如果桶中有剩余 Token 就可以一直取。如果没有剩余 Token,则需要等到桶中被放置了 Token 才行。

有的同学在看明白令牌桶的原理后就非常想去自己实现一个限流器应用到自己的项目里,em... 怎么说呢,造个轮子确实有利于自己水平提高,不过要是应用到商用项目里的话其实大可不必自己去造轮子,golang官方已经替我们造好轮子啦 ......~!

Golang 官方提供的扩展库里就自带了限流算法的实现,即 golang.org/x/time/rate。该限流器也是基于 Token Bucket(令牌桶) 实现的。

限流器的内部结构

time/rate包的Limiter类型对限流器进行了定义,所有限流功能都是通过基于Limiter类型实现的,其内部结构如下:

type Limiter struct {
 mu     sync.Mutex
 limit  Limit
 burst  int // 令牌桶的大小
 tokens float64
 last time.Time // 上次更新tokens的时间
 lastEvent time.Time // 上次发生限速器事件的时间(通过或者限制都是限速器事件)
}

其主要字段的作用是:

  • limit:limit字段表示往桶里放Token的速率,它的类型是Limit,是int64的类型别名。设置limit时既可以用数字指定每秒向桶中放多少个Token,也可以指定向桶中放Token的时间间隔,其实指定了每秒放Token的个数后就能计算出放每个Token的时间间隔了。

  • burst: 令牌桶的大小。

  • tokens: 桶中的令牌。

  • last: 上次往桶中放 Token 的时间。

  • lastEvent:上次发生限速器事件的时间(通过或者限制都是限速器事件)

可以看到在 timer/rate 的限流器实现中,并没有单独维护一个 Timer 和队列去真的每隔一段时间向桶中放令牌,而是仅仅通过计数的方式表示桶中剩余的令牌。每次消费取 Token 之前会先根据上次更新令牌数的时间差更新桶中Token数

大概了解了time/rate限流器的内部实现后,下面的内容我们会集中介绍下该组件的具体使用方法:

构造限流器

我们可以使用以下方法构造一个限流器对象:

limiter := rate.NewLimiter(10, 100);

这里有两个参数:

  • 第一个参数是 r Limit,设置的是限流器Limiter的limit字段,代表每秒可以向 Token 桶中产生多少 token。Limit 实际上是 float64 的别名。

  • 第二个参数是 b int,b 代表 Token 桶的容量大小,也就是设置的限流器 Limiter 的burst字段。

那么,对于以上例子来说,其构造出的限流器的令牌桶大小为 100, 以每秒 10 个 Token 的速率向桶中放置 Token。

除了给r Limit参数直接指定每秒产生的 Token 个数外,还可以用 Every 方法来指定向桶中放置 Token 的间隔,例如:

limit := rate.Every(100 * time.Millisecond);
limiter := rate.NewLimiter(limit, 100);

以上就表示每 100ms 往桶中放一个 Token。本质上也是一秒钟往桶里放 10 个。

使用限流器

Limiter 提供了三类方法供程序消费 Token,可以每次消费一个 Token,也可以一次性消费多个 Token。每种方法代表了当 Token 不足时,各自不同的对应手段,可以阻塞等待桶中Token补充,也可以直接返回取Token失败。

Wait/WaitN

func (lim *Limiter) Wait(ctx context.Context) (err error)
func (lim *Limiter) WaitN(ctx context.Context, n int) (err error)

Wait 实际上就是 WaitN(ctx,1)

当使用 Wait 方法消费 Token 时,如果此时桶内 Token 数组不足 (小于 N),那么 Wait 方法将会阻塞一段时间,直至 Token 满足条件。如果充足则直接返回。

这里可以看到,Wait 方法有一个 context 参数。我们可以设置 context 的 Deadline 或者 Timeout,来决定此次 Wait 的最长时间。

// 一直等到获取到桶中的令牌
err := limiter.Wait(context.Background())
if err != nil {
 fmt.Println("Error: ", err)
}

// 设置一秒的等待超时时间
ctx, _ := context.WithTimeout(context.Background(), time.Second * 1)
err := limiter.Wait(ctx)
if err != nil {
 fmt.Println("Error: ", err)
}

Allow/AllowN

func (lim *Limiter) Allow() bool
func (lim *Limiter) AllowN(now time.Time, n int) bool

Allow 实际上就是对 AllowN(time.Now(),1) 进行简化的函数。

AllowN 方法表示,截止到某一时刻,目前桶中数目是否至少为 n 个,满足则返回 true,同时从桶中消费 n 个 token。反之不消费桶中的Token,返回false。

对应线上的使用场景是,如果请求速率超过限制,就直接丢弃超频后的请求。

if limiter.AllowN(time.Now(), 2) {
    fmt.Println("event allowed")
} else {
    fmt.Println("event not allowed")
}

Reserve/ReserveN

func (lim *Limiter) Reserve() *Reservation
func (lim *Limiter) ReserveN(now time.Time, n int) *Reservation

Reserve 相当于 ReserveN(time.Now(), 1)

ReserveN 的用法就相对来说复杂一些,当调用完成后,无论 Token 是否充足,都会返回一个 *Reservation 对象。你可以调用该对象的Delay()方法,该方法返回的参数类型为time.Duration,反映了需要等待的时间,必须等到等待时间之后,才能进行接下来的工作。如果不想等待,可以调用Cancel()方法,该方法会将 Token 归还。

举一个简单的例子,我们可以这么使用 Reserve 方法。

r := limiter.Reserve()
f !r.OK() {
    // Not allowed to act! Did you remember to set lim.burst to be > 0 ?
    return
}
time.Sleep(r.Delay())
Act() // 执行相关逻辑

动态调整速率和桶大小

Limiter 支持创建后动态调整速率和桶大小:

  • SetLimit(Limit) 改变放入 Token 的速率

  • SetBurst(int) 改变 Token 桶大小

有了这两个方法,可以根据现有环境和条件以及我们的需求,动态地改变 Token 桶大小和速率。

总结

今天我们总结了 Golang 官方限流器的使用方法,它是一种令牌桶算实现的限流器。其中 Wait/WaitNAllow/AllowN 这两组方法在平时用的比较多,前者是消费Token时如果桶中Token不足可以让程序等待桶中新Token的放入(最好设置上等待时长)后者则是在桶中的Token不足时选择直接丢弃请求。

除了Golang官方提供的限流器实现,Uber公司开源的限流器uber-go/ratelimit也是一个很好的选择,与Golang官方限流器不同的是Uber的限流器是通过漏桶算法实现的,不过对传统的漏桶算法进行了改良,有兴趣的同学可以自行去体验一下。

到此这篇关于Go官方限流器的用法详解的文章就介绍到这了,更多相关Go 限流器内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: Go官方限流器的用法详解

本文链接: https://lsjlt.com/news/148133.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Go官方限流器的用法详解
    目录限流器的内部结构构造限流器使用限流器Wait/WaitNAllow/AllowNReserve/ReserveN动态调整速率和桶大小总结限流器是提升服务稳定性的非常重要的组件,可...
    99+
    2024-04-02
  • Golang官方限流器库实现限流示例详解
    目录前言例子实现小结前言 在翻Golang官方库的过程中,发现一个有趣的库golang.org/x/time ,里面只有一个类rate,研究了一下发现它是一个限流器,实现了很多的功能...
    99+
    2024-04-02
  • Golang官方限流器time/rate的使用与实现详解
    目录常见的限流算法固定窗口计数器算法滑动窗口计数器算法令牌桶算法漏桶算法time/rate主要方法各个方法的作用time/rate 是如何实现限流的源码解析常见的限流算法 ...
    99+
    2023-05-18
    Golang限流器time/rate使用 Golang限流器time/rate Golang限流器 Golang time/rate
  • Go官方工具链用法详解
    Go官方工具链 为了从任意目录运行Go官方工具链中工具命令(通过go命令), Go官方工具链安装目录下的bin子目录路径必须配置在PATH环境变量中。 当使用安装程序安装Go官方工具...
    99+
    2024-04-02
  • Go实现各类限流的方法
    前 言 在开发高并发系统时,我们可能会遇到接口访问频次过高,为了保证系统的高可用和稳定性,这时候就需要做流量限制,你可能是用的 Nginx 这种来控制请求,...
    99+
    2022-06-07
    GO 方法
  • Java限流实现的几种方法详解
    目录计数器信号量滑动窗口漏桶令牌桶测试示例代码计数器 计数器限流方式比较粗暴,一次访问就增加一次计数,在系统内设置每 N 秒的访问量,超过访问量的访问直接丢弃,从而实现限流访问。 具...
    99+
    2022-12-03
    Java限流 Java限流算法 Java限流方案
  • JavaRateLimiter的限流详解
    目录限流背景限流相关概念服务熔断服务降级服务隔离服务限流比较常见的限流方法限流工具类RateLimiter总结限流背景 在早期的计算机领域,限流技术(time limiting)被用...
    99+
    2024-04-02
  • 利用Redis实现访问次数限流的方法详解
    假设我们要做一个业务需求,这个需求就是限制用户的访问频次。比如1分钟内只能访问20次,10分钟内只能访问200次。因为是用户维度的场景,性能肯定是要首先考虑,那么适合这个场景的非Re...
    99+
    2024-04-02
  • go实现一个分布式限流器的方法步骤
    目录1. 接口定义2. LocalCounterLimiter3. LocalTokenBucketLimiter4. RedisCounterLimiter5. RedisToke...
    99+
    2024-04-02
  • 云服务器限制流量的解除方法
    1. 了解云服务器流量限制 在使用云服务器时,有些云服务提供商会对服务器的流量进行限制。这是为了防止滥用和保护服务器的稳定性。流量限制可以是每月总流量限制,也可以是每秒或每分钟的最大传输速率限制。 2. 解除云服务器流量限制的方法 方法一...
    99+
    2023-10-27
    流量 服务器 方法
  • 详解Redis实现限流的三种方式
     面对越来越多的高并发场景,限流显示的尤为重要。       当然,限流有许多种实现的方式,Redis具有很强大的功能,我用Redis实践了三...
    99+
    2024-04-02
  • 详解go mod 使用方法
    目录1、进入grammar文件夹2、初始化目录3、导入自定义的模块4、导入本地没有的模块常用命令1、初始化模块2 、获取远程的模块3、 查看当前依赖模块4、清除未使用到的依赖go m...
    99+
    2024-04-02
  • OpenTelemetry-go的SDK使用方法详解
    目录例子原理方法使用newExporternewResourcetrace.NewTracerProviderotel注意获取当前跨度设置span状态设置span属性记录错误设置活动...
    99+
    2024-04-02
  • 使用Java实现Redis限流的方法
    1、概述   限流的含义是在单位时间内确保发往某个模块的请求数量小于某个数值,比如在实现秒杀功能时,需要确保在10秒内发往支付模块的请求数量小于500个。限流...
    99+
    2024-04-02
  • Go语言JSON解析器gjson使用方法详解
    目录gjson安装使用gjson GJSON 是一个Go包,它提供了一种从json文档中获取值的快速简单的方法。它具有单行检索、点符号路径、迭代和解析 json 行等功能。 还可以查...
    99+
    2022-12-08
    Go 解析器gjson Go JSON解析器
  • 详解5种Java中常见限流算法
    目录01固定窗口02滑动窗口03漏桶算法04令牌桶05滑动日志06分布式限流07总结1.瞬时流量过高,服务被压垮? 2.恶意用户高频光顾,导致服务器宕机? 3.消息消费过快,导致数据...
    99+
    2023-05-14
    Java常见限流算法 Java限流算法 Java限流
  • 详解Golang实现请求限流的几种办法
    简单的并发控制 利用 channel 的缓冲设定,我们就可以来实现并发的限制。我们只要在执行并发的同时,往一个带有缓冲的 channel 里写入点东西(随便写啥...
    99+
    2024-04-02
  • 阿里云服务器的流量限制详解
    本文将详细介绍阿里云服务器的流量限制,包括流量类型、流量上限、流量计费方式等内容,帮助用户更好地理解和使用阿里云服务器。 在使用阿里云服务器时,了解服务器的流量限制是非常重要的。流量是指在一定时间内通过网络传输的数据量,主要包括带宽流量和数...
    99+
    2024-01-26
    阿里 详解 流量
  • Redis实现限流器的方法有哪些
    这篇文章主要介绍了Redis实现限流器的方法有哪些的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Redis实现限流器的方法有哪些文章都会有所收获,下面我们一起来看看吧。 ...
    99+
    2024-04-02
  • 云服务器流量限制怎么解决方法
    首先,云服务器的流量限制可以通过配置VLAN、限制下载上传速度、使用负载均衡器等方式来解决。例如,如果用户的网站需要访问大量的高并发流量,可以将用户的服务器分为多个VLAN,并配置每个VLAN下的用户访问流量,以确保高并发流量可以被合理利用...
    99+
    2023-10-27
    解决方法 流量 服务器
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作