uber go/ratelimit算法是如何工作的?

uber go/ratelimit算法是如何工作的?,go,rate-limiting,Go,Rate Limiting,我试图理解uber对ratelimit的开源实现,但有点困惑 完整代码如下所示: // Take blocks to ensure that the time spent between multiple // Take calls is on average time.Second/rate. func (t *limiter) Take() time.Time { newState := state{} taken := false for !taken {

我试图理解uber对ratelimit的开源实现,但有点困惑

完整代码如下所示:

// Take blocks to ensure that the time spent between multiple
// Take calls is on average time.Second/rate.
func (t *limiter) Take() time.Time {
    newState := state{}
    taken := false
    for !taken {
        now := t.clock.Now()

        previousStatePointer := atomic.LoadPointer(&t.state)
        oldState := (*state)(previousStatePointer)

        newState = state{}
        newState.last = now

        // If this is our first request, then we allow it.
        if oldState.last.IsZero() {
            taken = atomic.CompareAndSwapPointer(&t.state, previousStatePointer, unsafe.Pointer(&newState))
            continue
        }

        // sleepFor calculates how much time we should sleep based on
        // the perRequest budget and how long the last request took.
        // Since the request may take longer than the budget, this number
        // can get negative, and is summed across requests.
        newState.sleepFor += t.perRequest - now.Sub(oldState.last)
        // We shouldn't allow sleepFor to get too negative, since it would mean that
        // a service that slowed down a lot for a short period of time would get
        // a much higher RPS following that.
        if newState.sleepFor < t.maxSlack {
            newState.sleepFor = t.maxSlack
        }
        if newState.sleepFor > 0 {
            newState.last = newState.last.Add(newState.sleepFor)
        }
        taken = atomic.CompareAndSwapPointer(&t.state, previousStatePointer, unsafe.Pointer(&newState))
    }
    t.clock.Sleep(newState.sleepFor)
    return newState.last
}
//使用块来确保在多个
//接听电话是平均时间。秒/率。
func(t*限制器)Take()time.time{
newState:=状态{}
假设:=假
因为!吃了{
now:=t.clock.now()
previousStatePointer:=atomic.LoadPointer(&t.state)
oldState:=(*状态)(previousStatePointer)
newState=状态{}
newState.last=现在
//如果这是我们的第一个请求,那么我们允许它。
如果oldState.last.IsZero(){
take=atomic.CompareAndSwapPointer(&t.state,previousStatePointer,unsafe.Pointer(&newState))
持续
}
//sleepFor计算我们应该睡眠的时间
//perRequest预算以及上次请求所用的时间。
//由于请求可能需要比预算更长的时间,此数字
//可以为负数,并在请求之间求和。
newState.sleepFor+=t.perRequest-now.Sub(oldState.last)
//我们不应该让sleepFor变得太消极,因为这意味着
//在短时间内速度大幅降低的服务将获得
//之后的RPS要高得多。
如果newState.sleepFor0{
newState.last=newState.last.Add(newState.sleepFor)
}
take=atomic.CompareAndSwapPointer(&t.state,previousStatePointer,unsafe.Pointer(&newState))
}
t、 clock.Sleep(newState.sleepFor)
返回newState.last
}
我意识到这是一个无锁算法,但我对这个主题知之甚少


如果有人碰巧知道这个算法并给我一些答案/文档/博客,谢谢。我的问题实际上是试图理解为什么这是一个无锁的算法。也许考虑更新你的问题,然后,谢谢你的建议。这不是一个想象中的“无锁算法”。这只是一些模拟自变量的CAS舞蹈。CAS不是非阻塞算法的一部分吗?对不起,我的问题实际上是试图理解为什么这是一个无锁的算法。也许考虑更新你的问题,然后,谢谢你的建议。这不是一个想象中的“无锁算法”。这只是一些模拟互斥的CAS舞蹈。CAS不是非阻塞算法的一部分吗?