• 简单令牌桶实现


    主要思路:
    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()
    }
    
    
  • 相关阅读:
    Tomcat windows服务器配置多个Tomcat
    Sharepoint开发实用技巧(1)
    戏说MOSS关于EventHander编程
    协作应用程序标记语言 CAML 点滴(一)
    MOSS开发手记(3)
    协作应用程序标记语言 CAML点滴(二)
    MOSS项目开发(1) 项目计划,重点及文档
    MOSS项目开发(4) 开发文档的规范
    MOSS开发手记(2)
    Asp.Net页面执行流程分析
  • 原文地址:https://www.cnblogs.com/chq3272991/p/15667859.html
Copyright © 2020-2023  润新知