我是靠谱客的博主 酷炫日记本,最近开发中收集的这篇文章主要介绍令牌桶算法和漏桶算法有什么区别_Go并发实战--限流算法,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

28c983ac2bbfe3e56c49552bf308ecdf.png

高并发系统为了服务的可用性面对高流量及qps高峰时通常有三种常见的应对措施:缓存、降级和限流。这一篇我们来看一下限流及go相应的实现。 限流算法通常有这么几种:计数器、令牌痛、漏桶,这几个算法的优缺点在这里就不多说了,网上有大量的文章介绍这几个算法,大家也可以借鉴我限流算法的那篇文章。 这里就这几种算法的思想借助go的API来实现一下:

计数器限流

这里用到的并发相关的API 主要是sync.Mutex 我们通过设定一个计数器ReqCount,当ReqCount大于MaxCount(计数器最大值)时不发放令牌(token),过来的请求因拿不到令牌直接返回或者触发其他的拒绝策略。 因为计数器的操作是一个典型的先判断再操作的竞态条件,并且存在另外一个专门置0的go协程,如果不加锁,在并发场景下发生问题的概率是非常大的,所以使用sync.Mutex,保证了操作的原子性。 计数器比较简单,下面来看一下实现的代码:

type AbandonReqLimitService struct {
    Interval time.Duration // 设置计数器的时间间隔
    MaxCount int // 计数器的最大值
    Lock     sync.Mutex // 锁
    ReqCount int // 计数器
}

func CreateAbandonReqLimitService(interval time.Duration, maxCount int) *AbandonReqLimitService {
    reqLimit := &AbandonReqLimitService{
        Interval: interval,
        MaxCount: maxCount,
    }
    go func() { // 开启一个go协程来定时更新计数器
        ticker := time.NewTicker(interval) // go中的定时器
        for {
            <-ticker.C
            reqLimit.Lock.Lock()
            reqLimit.ReqCount = 0
            reqLimit.Lock.Unlock()
        }
    }()
    return reqLimit
}

func (reqLimit *AbandonReqLimitService) GetTokenAbandonRequest() bool { // 取令牌函数
    reqLimit.Lock.Lock()
    defer reqLimit.Lock.Unlock()
    if reqLimit.ReqCount < reqLimit.MaxCount {
        reqLimit.ReqCount += 1
        return true
    } else {
        return false
    }
}

令牌桶限流

这里涉及的API 主要是channel,利用的就是channel的阻塞操作。 我们把一个指定尺寸channel,相当于一个指定容量的令牌桶,每一个空闲位置就是一个令牌。由于channel满时就无法向其中加元素,所以我们就可以以固定的速率消费channel中的消息(释放空间相当于添加令牌),取令牌就是添加一条消息,当令牌桶满时就无法正常添加消息(取令牌)了,这样就利用channel来构造了一个限流器。 下面来看一下代码:

type NotAbandonReqLimitService struct {
    TokenPool chan bool // 令牌桶
}
func CreateNewRequestLimitService(interval time.Duration, maxCnt int) *NotAbandonReqLimitService {
    reqLimit := &NotAbandonReqLimitService{}
    reqLimit.TokenPool = make(chan bool, maxCnt) // 令牌桶最大容量
    go func() {
        tmpStr := strconv.Itoa(maxCnt)
        maxCntInt64,_ := strconv.ParseInt(tmpStr, 10, 64)
        ticker := time.NewTicker( time.Duration(interval.Nanoseconds()/(maxCntInt64*1000*1000))* time.Millisecond) // 匀速添加令牌,1s/最大qps 就是添加的速率
        for {
            <- ticker.C
            <- reqLimit.TokenPool
        }
    }()
    return reqLimit
}
func (reqLimit *NotAbandonReqLimitService) GetTokenNotAbandonRequest() {
    reqLimit.TokenPool <- true // 消费令牌
}

在常用限流算法go的实现中,关于sync、chan的使用大致就是以上,这两个demo挺简单的,可以由浅入深帮助大家理解一下go并发编程及Mutex、chan 的API使用。 关于限流算法暂时就说这么多。

最后

以上就是酷炫日记本为你收集整理的令牌桶算法和漏桶算法有什么区别_Go并发实战--限流算法的全部内容,希望文章能够帮你解决令牌桶算法和漏桶算法有什么区别_Go并发实战--限流算法所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部