美文网首页
2019-07-25

2019-07-25

作者: 肖四 | 来源:发表于2019-07-25 21:48 被阅读0次
// The methods AllowN, ReserveN, and WaitN consume n tokens.
type Limiter struct {
    limit Limit
    burst int

    mu     sync.Mutex
    tokens float64
    // last is the last time the limiter's tokens field was updated
    last time.Time
    // lastEvent is the latest time of a rate-limited event (past or future)
    lastEvent time.Time
}

// Limit returns the maximum overall event rate.
func (lim *Limiter) Limit() Limit {
    lim.mu.Lock()
    defer lim.mu.Unlock()
    return lim.limit
}

// Burst returns the maximum burst size. Burst is the maximum number of tokens
// that can be consumed in a single call to Allow, Reserve, or Wait, so higher
// Burst values allow more events to happen at once.
// A zero Burst allows no events, unless limit == Inf.
func (lim *Limiter) Burst() int {
    return lim.burst
}

// NewLimiter returns a new Limiter that allows events up to rate r and permits
// bursts of at most b tokens.
func NewLimiter(r Limit, b int) *Limiter {
    return &Limiter{
        limit: r,
        burst: b,
    }
}


// Allow is shorthand for AllowN(time.Now(), 1).
func (lim *Limiter) Allow() bool {
    return lim.AllowN(time.Now(), 1)
}

// AllowN reports whether n events may happen at time now.
// Use this method if you intend to drop / skip events that exceed the rate limit.
// Otherwise use Reserve or Wait.
func (lim *Limiter) AllowN(now time.Time, n int) bool {
    return lim.reserveN(now, n, 0).ok
}



// Wait is shorthand for WaitN(ctx, 1).
func (lim *Limiter) Wait(ctx context.Context) (err error) {
    return lim.WaitN(ctx, 1)
}

// WaitN blocks until lim permits n events to happen.
// It returns an error if n exceeds the Limiter's burst size, the Context is
// canceled, or the expected wait time exceeds the Context's Deadline.
// The burst limit is ignored if the rate limit is Inf.
func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) {
    if n > lim.burst && lim.limit != Inf {
        return fmt.Errorf("rate: Wait(n=%d) exceeds limiter's burst %d", n, lim.burst)
    }
    // Check if ctx is already cancelled
    select {
    case <-ctx.Done():
        return ctx.Err()
    default:
    }
    // Determine wait limit
    now := time.Now()
    waitLimit := InfDuration
    if deadline, ok := ctx.Deadline(); ok {
        waitLimit = deadline.Sub(now)
    }
    // Reserve
    r := lim.reserveN(now, n, waitLimit)
    if !r.ok {
        return fmt.Errorf("rate: Wait(n=%d) would exceed context deadline", n)
    }
    // Wait if necessary
    delay := r.DelayFrom(now)
    if delay == 0 {
        return nil
    }
    t := time.NewTimer(delay)
    defer t.Stop()
    select {
    case <-t.C:
        // We can proceed.
        return nil
    case <-ctx.Done():
        // Context was canceled before we could proceed.  Cancel the
        // reservation, which may permit other events to proceed sooner.
        r.Cancel()
        return ctx.Err()
    }
}


// Reserve is shorthand for ReserveN(time.Now(), 1).
func (lim *Limiter) Reserve() *Reservation {
    return lim.ReserveN(time.Now(), 1)
}

// reserveN is a helper method for AllowN, ReserveN, and WaitN.
// maxFutureReserve specifies the maximum reservation wait duration allowed.
// reserveN returns Reservation, not *Reservation, to avoid allocation in AllowN and WaitN.
func (lim *Limiter) reserveN(now time.Time, n int, maxFutureReserve time.Duration) Reservation {
    lim.mu.Lock()

    if lim.limit == Inf {
        lim.mu.Unlock()
        return Reservation{
            ok:        true,
            lim:       lim,
            tokens:    n,
            timeToAct: now,
        }
    }

    now, last, tokens := lim.advance(now)

    // Calculate the remaining number of tokens resulting from the request.
    tokens -= float64(n)

    // Calculate the wait duration
    var waitDuration time.Duration
    if tokens < 0 {
        waitDuration = lim.limit.durationFromTokens(-tokens)
    }

    // Decide result
    ok := n <= lim.burst && waitDuration <= maxFutureReserve

    // Prepare reservation
    r := Reservation{
        ok:    ok,
        lim:   lim,
        limit: lim.limit,
    }
    if ok {
        r.tokens = n
        r.timeToAct = now.Add(waitDuration)
    }

    // Update state
    if ok {
        lim.last = now
        lim.tokens = tokens
        lim.lastEvent = r.timeToAct
    } else {
        lim.last = last
    }

    lim.mu.Unlock()
    return r
}


package main
 
import (
    "context"
    "fmt"
    "time"
 
    "golang.org/x/time/rate"
)
 
func main() {
    l := rate.NewLimiter(2, 5)
    ctx := context.Background()
    start := time.Now()
    // 要处理二十个事件
    for i := 0; i < 20; i++ {
        l.Wait(ctx)
        // dosomething
    }
    fmt.Println(time.Since(start)) 
}


相关文章

  • 2019-07-27

    2019-07-25 毛雅亭 字数 558 · 阅读 8 2019-06-02 18:39 ...

  • Lan的ScalersTalk第四轮新概念朗读持续力训练Day

    练习材料: [Day 1763 2019-07-25] Lesson 25-3 Non-auditory effe...

  • 文先森的日常

    日精进打卡第359天 姓名:李文杰 (四爷); 公司:中国太平人寿; 日期:2019-07-25 【知~学习】 ...

  • 巧解妙析彰显和谐之风

    双阳148李春梅 字数 899 · 阅读 38 2019-07-25 21:26 ———观摩杭州师范学校王崧舟老师...

  • 【®感恩日记第1183篇》 - 夏令营第19天

    2019-07-25 05:02 读经人: 妈妈,冲冲 读经内容:《黄帝内经素问-上古天真论篇01》《孟子:公孙丑...

  • 14. 用户调研

    P2总结 逻辑分析能力 需求理解 项目推进屏幕快照 2019-07-25 下午6.53.17.png 专业职业才能...

  • 那一碗还没有下的饺子

    时间:2019-07-25 18:40 周四 地点:成都 天气:晴朗好热 心情:有些自豪 关键字:学会爱人 不知道...

  • 深度践行12/90

    2019-07-25 今日天气:早上阴,白天阵雨 【宣言】做更好的自己 #深度践行 教练姓名:谭福翠 孩子年龄+性...

  • 2019-07-25

    2019-07-25 姓名:郭祥华 组别:315期六项精进努力一组 【日精进打卡第566】 【知~学习】 背诵《...

  • 2019-07-25跑步记录

    时间:2019-07-25 20:30 线路:天马河绿道 成绩:5公里用时28分30秒 7月:112公里 感受:高...

网友评论

      本文标题:2019-07-25

      本文链接:https://www.haomeiwen.com/subject/bnnkrctx.html