简单令牌桶实现

简单令牌桶实现主要思路: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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 计算机专业男人喜欢什么样的女人,说实在的,其实男人真正喜欢的女人,就三个特征…

    计算机专业男人喜欢什么样的女人,说实在的,其实男人真正喜欢的女人,就三个特征…男人和女人有什么不同?大概是后者的世界里只有爱情,前者的世界里除了爱情,还有对金钱与权力的渴望。人比人气死人。有些女人从来都不缺追求者,有些女人从来都没有追求者,很多时候并不明白,她到底比她差在哪里?这还不算扎心的,有些女人绞尽脑汁,都没能守住自己的爱情,而有些女人看着都没怎么费力,却保卫了自己的爱情。也许我们都要深思,那些一直“幸运”的女人到底有什么秘诀。对于感情,女人一般会有的疑问,无非两个。…

    2022年7月25日
    44
  • Flink 入门教程

    实时流处理的应用场景现在的社会已然进入了大数据AI时代,各行各业都有大量的数据需要处理,并希望从数据中挖掘价值。下面简单举几个例子:物联网中各种行为结果数据的实时收集分析金融行业中各种交易行为数据结果的实时收集分析电商行业中用户的浏览点击等行为数据结果的实时收集分析…实时流处理的目标低延迟高吞吐正确性可容错(即可以中断,并可以恢复且保证exactlyonce)顺序性(…

    2022年4月4日
    51
  • centos7配置sftp_怎么修改服务器sftp端口

    centos7配置sftp_怎么修改服务器sftp端口CentOS7修改sftp端口修改sftp默认端口为12322vi/etc/ssh/ssh_config把Port22改成Port12322vi/etc/ssh/sshd_config把Port22改成Port12322修改之后重启servicesshdrestart

    2022年9月14日
    1
  • java枚举类型enum用法(java定义枚举常量类)

    文章目录枚举类的使用如何定义枚举类方式一:jdk5.0之前,自定义枚举类方式二:jdk5.0,可以使用enum关键字定义枚举类Enum类的主要方法toString()values()valueOf(StringobjName)使用enum关键字定义的枚举类实现接口的情况情况一:实现接口,在enum类中实现抽象方法情况二:让枚举类的对象分别实现接口中的抽象方法枚举类的使用枚举类的理解:类的对象只有有限个,确定的。我们称此类为枚举类当需要定义一组常量时,强烈建议使用枚举类如果枚举类中只有一个对象,则

    2022年4月16日
    39
  • waitforsingleobject的作用_效率理论

    waitforsingleobject的作用_效率理论MicrosoftWindows平台中两种最常用的锁定方法为WaitForSingleObject和EnterCriticalSection。WaitForSingleObject是一个过载MicrosoftAPI,可用于检查和修改许多不同对象(如事件、作业、互斥体、进程、信号、线程或计时器)的状态。WaitForSingleObject的一个不足之处是它会始终获取内核的锁

    2022年9月19日
    3
  • 欢聚时代一面

    欢聚时代一面

    2022年1月24日
    55

发表回复

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

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