简单令牌桶实现

简单令牌桶实现主要思路:1.创建channel,通过定时器定时往channel中写入令牌,返回令牌桶本身(channel);2.判断请求是否可以拿到令牌;packagemainimport(&quot

大家好,又见面了,我是你们的朋友全栈君。

主要思路:
1.创建channel,通过定时器定时往channel中写入令牌,返回令牌桶本身(channel);
2.判断请求是否可以拿到令牌;

package main

import (
	"context"
	"fmt"
	"time"
)

func getBucket(capacityPs, maxCapacity int) (chan struct{}, *time.Ticker) {
	var bucketToken = make(chan struct{}, maxCapacity)
	ticker := time.NewTicker(time.Second / time.Duration(capacityPs))
	go func() {
		for {
			select {
			case <-ticker.C:
				bucketToken <- struct{}{}
			default:
			}
		}
	}()
	return bucketToken, ticker
}

func getToken(ctx context.Context, bucket *chan struct{}, wait bool) bool {
	if wait {
		select {
		case <-*bucket:
			return true
		case <-ctx.Done():
			fmt.Println("请求超时...")
			return false
		}
	} else { // 不阻塞
		select {
		case <-*bucket:
			return true
		default:
			return false
		}
	}
}

// 模拟qps 100, 超时等待时间为1s,模拟1000个请求进来
// 令牌桶最大每秒产生30个令牌,最大突发为50(桶最大容量)
func test1() {
	bucket, ticker := getBucket(30, 50)
	i := 0
	total := 0
	fail := 0
	go func() {
		for { // qps 100
			i++
			time.Sleep(time.Millisecond * 10)
			ctx, _ := context.WithTimeout(context.Background(), time.Millisecond*100)
			ok := getToken(ctx, &bucket, false)
			if ok {
				total++
			} else {
				fail++
			}
			fmt.Println("当前获取token是否成功:", ok)
			if i >= 1000 {
				ticker.Stop()
				break
			}
		}
	}()
	time.Sleep(time.Second * 20)
	fmt.Println(i, total, fail)
}

// 模拟qps 100, 超时等待时间为1s,模拟1000个请求进来
// 令牌桶最大每秒产生30个令牌,最大突发为50(桶最大容量)
func test2() {
	bucket, ticker := getBucket(30, 50)
	i := 0
	total := 0
	fail := 0
	go func() {
		for { // qps 100
			i++
			time.Sleep(time.Millisecond * 10)
			ctx, _ := context.WithTimeout(context.Background(), time.Millisecond*20)
			ok := getToken(ctx, &bucket, true)
			if ok {
				total++
			} else {
				fail++
			}
			fmt.Println("当前获取token是否成功:", ok)
			if i >= 1000 {
				ticker.Stop()
				break
			}
		}
	}()
	time.Sleep(time.Second * 20)
	fmt.Println(i, total, fail)
}

func main() {
	//test1()
	test2()
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/155395.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 网站友链html代码_html底部友情链接代码

    网站友链html代码_html底部友情链接代码使用PHPcms建站的时候会经常遇到,添加友情链接。那么如何在phpcms的网站里面添加友情链接呢{pc:linkaction=”type_list”typeid=”0″siteid=”1″linktype=”1″order=”listorderDESC”num=”8″return=”pic_link”}{loop$pic_link$v}{$v[name]}{/loop}{/…

    2022年10月24日
  • L3-002 特殊堆栈(树状数组+二分)「建议收藏」

    L3-002 特殊堆栈(树状数组+二分)「建议收藏」原题链接堆栈是一种经典的后进先出的线性结构,相关的操作主要有“入栈”(在堆栈顶插入一个元素)和“出栈”(将栈顶元素返回并从堆栈中删除)。本题要求你实现另一个附加的操作:“取中值”——即返回所有堆栈中元素键值的中值。给定 N 个元素,如果 N 是偶数,则中值定义为第 N/2 小元;若是奇数,则为第 (N+1)/2 小元。输入格式:输入的第一行是正整数 N(≤10​5​​ )。随后 N 行,每行给出一句指令,为以下 3 种之一:Push keyPopPeekMedian其中 key 是不超过

    2022年8月9日
  • 解决Navicat for MySQL 连接 Mysql 8.0.11 出现1251- Client does not support authentication protocol 错误

    解决Navicat for MySQL 连接 Mysql 8.0.11 出现1251- Client does not support authentication protocol 错误今天在电脑上安装了Mysql8.0.11,然后又屁颠屁颠地安装了NavicatforMySQL,打开Navicat准备链接数据库的时候出现了如下提示:上网搜索解决方案,网上说出现这种情况的原因是:mysql8之前的版本中加密规则是mysql_native_password,而在mysql8之后,加密规则是caching_sha2_password,解决问题方法有两种:方法…

    2022年5月30日
  • 【java实现网址转换为二维码】「建议收藏」

    【java实现网址转换为二维码】「建议收藏」我们可以实现图片二维码转换为网址,或者将网址转换为伪二维码(与普通二维码有区别,因为没有定位点,转换成的二维码只包含信息)。

    2022年9月3日
  • 二进制加减法运算法则例子_php运算符

    二进制加减法运算法则例子_php运算符如果采用与十进制减法相同的方法,那么从一个较大的二进制数中减去一个较小的无符号二进制数就很容易了。示例如下:01101(十进制数13)–00111(十进制数7)———-位0上的减法非常简单:01101–00111———-0下一个位置上执行(0-1),要向左边的相邻位借1,其结果是从2中减去1:01001–00111———-10再下一位上,又要向左…

    2022年9月25日
  • 【Java面试系列】ElasticSearch面试题

    【Java面试系列】ElasticSearch面试题目录1.Elasticsearch面试题2.Elasticsearch面试题解析1、elasticsearch了解多少,说说你们公司es的集群架构,索引数据大小,分片有多少,以及一些调优手段。1.1、设计阶段调优1.2、写入调优1.3、查询调优1.4、其他调优2、elasticsearch的倒排索引是什么3、elasticsearch索引数据多了…

    2022年9月12日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号