kubernetes源码工具包wait的使用原理剖析

官方解释JitterUntil工具的使用说明

 //管道在关闭之前 周期执行函数f
// JitterUntil loops until stop channel is closed, running f every period.
//
// If jitterFactor is positive, the period is jittered before every run of f.
// If jitterFactor is not positive, the period is unchanged and not jittered.
//
// If sliding is true, the period is computed after f runs. If it is false then
// period includes the runtime for f.
//
// Close stopCh to stop. f may not be invoked if stop channel is already
// closed. Pass NeverStop to if you don't want it stop.

源码目录

k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go

源码

func JitterUntil(f func(), period time.Duration, jitterFactor float64, sliding bool, stopCh <-chan struct{}) {
    var t *time.Timer
    var sawTimeout bool

    for {
        select {
        case <-stopCh:
            return
        default:
        }

        jitteredPeriod := period
        if jitterFactor > 0.0 {
            jitteredPeriod = Jitter(period, jitterFactor)
        }

        if !sliding {
            t = resetOrReuseTimer(t, jitteredPeriod, sawTimeout)
        }

        func() {
            defer runtime.HandleCrash()
            f()
        }()

        if sliding {
            t = resetOrReuseTimer(t, jitteredPeriod, sawTimeout)
        }

        // NOTE: b/c there is no priority selection in golang
        // it is possible for this to race, meaning we could
        // trigger t.C and stopCh, and t.C select falls through.
        // In order to mitigate we re-check stopCh at the beginning
        // of every loop to prevent extra executions of f().
        select {
        case <-stopCh:
            return
        case <-t.C:
            sawTimeout = true
        }
    }
}
// resetOrReuseTimer avoids allocating a new timer if one is already in use.
// Not safe for multiple threads.
func resetOrReuseTimer(t *time.Timer, d time.Duration, sawTimeout bool) *time.Timer {
    if t == nil {
        return time.NewTimer(d)
    }
    if !t.Stop() && !sawTimeout {
        <-t.C
    }
    t.Reset(d)
    return t
}

sliding 滑动处理 如果为true,计时包括执行 f 函数的花费时间,如果为false,不包含执行时间


简单使用例子

func main() {

    stop := make(chan struct{})

    go func() {
        fmt.Printf("sleep 10!\n")

        time.Sleep(10 * time.Second)
        var a struct{}
        stop <- a
    }()

    f := func() {
        time.Sleep(1 * time.Second)
        fmt.Printf("hello world!\n")
    }
    //100000000
    Until(f, 1*time.Second, stop)

    //NonSlidingUntil(f, 1*time.Second, stop)

    fmt.Println("the chan closed")

}

执行结果

go run jitter.go
sleep 10!
hello world!
hello world!
hello world!
hello world!
hello world!
the chan closed

func main() {

    stop := make(chan struct{})

    go func() {
        fmt.Printf("sleep 10!\n")

        time.Sleep(10 * time.Second)
        var a struct{}
        stop <- a
    }()

    f := func() {
        time.Sleep(1 * time.Second)
        fmt.Printf("hello world!\n")
    }
    //100000000
    //Until(f, 1*time.Second, stop)

    NonSlidingUntil(f, 1*time.Second, stop)

    fmt.Println("the chan closed")

}

执行结果

go run jitter.go
sleep 10!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
the chan closed

kubernetes 的源码好多地方都用到这个函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值