chenyahui / chenyahui.github.io

My blog
http://www.cyhone.com
0 stars 2 forks source link

Golang 官方限流器 time/rate 使用介绍 | 编程沉思录 #48

Open chenyahui opened 4 years ago

chenyahui commented 4 years ago

https://www.cyhone.com/articles/usage-of-golang-rate/#more

本主题为系列文章,分上下两篇。本文主要介绍 time/rate 的具体使用方法,另外一篇文章 《Golang 限流器 time/rate 实现剖析》 则着重介绍其内部实现原理。 限流器是后台服务中的非常重要的组件,可以用来限制请求速率,保护服务,以免服务过载。 限流器的实现方法有很多种,例如滑动窗口法、Token Bucket、Leaky Bucket 等。 其实 Golang 标准库中就自带

lysShub commented 2 years ago

NewLimiter第二个参数可不是容量大小,它是初始并发量。这个很容易让人误解,希望作者修改下

chenyahui commented 2 years ago

@lysShub NewLimiter第二个参数可不是容量大小,它是初始并发量。这个很容易让人误解,希望作者修改下

我的理解是burst是最大突增并发数,只有桶内还有剩余令牌的时候,就能够消费。这也是令牌桶相比于漏桶的优势。从作用来,的确是并发量,但从结构上来看,代表的也是桶的容量没啥问题。 不过我晚些对burst参数多做一些说明

lysShub commented 2 years ago

@chenyahui

@lysShub NewLimiter第二个参数可不是容量大小,它是初始并发量。这个很容易让人误解,希望作者修改下

我的理解是burst是最大突增并发数,只有桶内还有剩余令牌的时候,就能够消费。这也是令牌桶相比于漏桶的优势。从作用来,的确是并发量,但从结构上来看,代表的也是桶的容量没啥问题。 不过我晚些对burst参数多做一些说明

并不是并发量,顶多可以理解为初始并发量;实际的并发还是第一个参数决定的

    var xRatelimit *xrate.Limiter = xrate.NewLimiter(5, 100)
    start := time.Now()
    for i := 0; i < 5; i++ {
        xRatelimit.Wait(context.Background())
    }
    fmt.Println(time.Since(start))
    start = time.Now()
    for i := 0; i < 100; i++ {
        xRatelimit.Wait(context.Background())
    }
    fmt.Println(time.Since(start))
lysShub commented 2 years ago

并且并不能把第二个参数设置为0

runzhi214 commented 1 year ago

@lysShub 你的理解是错误的。 作者说的是没错的,第二个参数就是令牌桶的大小,且初始状态下令牌桶是满的。 看这个例子,每0.1秒生产1个令牌,最大容量50。

  1. 当一次消费51个令牌时报错
  2. 一次消费全部令牌再次消费全部令牌需要等待5秒
    
    package main

import ( "context" "fmt" "golang.org/x/time/rate" "log" "time" )

func test2() { // at most 10 times per second // aat most 50 buckets held BucketSize := 50 e := rate.Every(time.Millisecond 100) var xRatelimit rate.Limiter = rate.NewLimiter(e, BucketSize)

start := time.Now()
err := xRatelimit.WaitN(context.Background(), BucketSize)
if err != nil {
    log.Fatal(err)
}
fmt.Println(time.Since(start))
err = xRatelimit.WaitN(context.Background(), BucketSize)
if err != nil {
    log.Fatal(err)
}
fmt.Println(time.Since(start))

err = xRatelimit.WaitN(context.Background(), BucketSize+1)
if err != nil {
    log.Fatal(err)
}

}

func main() { test2() }

runzhi214 commented 1 year ago

@lysShub NewLimiter第二个参数可不是容量大小,它是初始并发量。这个很容易让人误解,希望作者修改下 作者说的是对的,你说的是错的。这会让人误会的,麻烦修改下

cs-moushuai commented 10 months ago

现有的漏桶,令牌桶限流策略我只看到了如何限制请求个数,那又如何限制带宽呢?