简单令牌桶实现

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


相关推荐

  • think in java一_Think in Java(一):Java基础「建议收藏」

    think in java一_Think in Java(一):Java基础「建议收藏」一.OOP的特点(1)万物皆为对象;(2)程序是对象的集合,他们通过发送信息来告诉彼此所要做的;(3)每个对象都有自己的由其他对象所构成的存储;(4)每个对象都拥有它的类型;(5)某一特定类型的对象都可以接收同样的消息;二.Java比C++简单?(1)Java有垃圾回收器,不用手动销毁对象;(2)Java使用单根继承;(3)Java只能以一种方式创建对象(在堆上创建);三….

    2022年7月8日
    23
  • java键盘钩子_java 写的低级鼠标键盘钩子示例

    java键盘钩子_java 写的低级鼠标键盘钩子示例需要到http://java.net/projects/jna/downloads下载jna.jar和platform.jar(参考http://my.oschina.net/penngo/blog/12356):1.[代码][Java]代码packagejna_test;importcom.sun.jna.platform.win32.*;importcom.sun.jna.plat…

    2022年5月6日
    41
  • 什么是UDP攻击_机器人打电话营销效果

    什么是UDP攻击_机器人打电话营销效果UDP协议UDP是一个简单的面向数据报的运输层协议,也是最常见的作为流量攻击最多的一种协议,需要用到UDP的主要都是视频通讯,枪战类实时通讯的游戏类。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但并不保证它们能到达目的地。由于UDP传输数据前传输数据之前源端和终端不建立连接,且没有超时重发等机制,故而传输速度很快。UDP攻击UDP攻击是DDoS攻击的一种,是典型的流量型攻击。就好比学校中午放学时的食堂,学生大量飞奔食堂,但食堂窗口就那么多,学生数量太多,就只能挤在窗口前等待。

    2022年10月2日
    0
  • 【数据结构】十大排序「建议收藏」

    打开算法大门,从排序开始

    2022年4月13日
    48
  • 多线程CreateThread函数的用法

    多线程CreateThread函数的用法CreateThread当使用CreateProcess调用时,系统将创建一个进程和一个主线程。CreateThread将在主线程的基础上创建一个新线程,大致做如下步骤:1在内核对象中分配一个线程标

    2022年7月4日
    31
  • weka怎么安装_we是什么安装方式

    weka怎么安装_we是什么安装方式1什么是看板管理首先我们先两张现实中的看板系统,能够有助于我们理解看板管理系统。大家常见的应该是实体看板,适合布置在团队所有成员都在一个办公室工作的环境。它的优点很明显,方便工作成员展示和查看自

    2022年8月4日
    5

发表回复

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

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