client-go和golang源码中的技巧( 五 )

var DefaultRetry = wait.Backoff{Steps:5,Duration: 1 * time.Second,Factor:0,Jitter:0.5,}结果:2019-07-05 10:21:49.5993445 +0800 CST m=+2.3826691012019-07-05 10:21:50.9026701 +0800 CST m=+3.6859947012019-07-05 10:21:52.3759019 +0800 CST m=+5.1592264012019-07-05 10:21:53.7086265 +0800 CST m=+6.4919510012019-07-05 10:21:54.9283913 +0800 CST m=+7.711715901timed out waiting for the condition=> Factor非0且Jitter为0时 , 对duration的调整如下
if b.Factor != 0 {b.Duration = time.Duration(float64(b.Duration) * b.Factor)if b.Cap > 0i < 20; i++ {err := l.Wait(ctx)if nil != err{fmt.Println(err)fmt.Println(time.Since(start))return}go f(ctx)}fmt.Println(time.Since(start))}结果:5.0000404s下例中 , 如果每秒处理的令牌小于2 , 调度频率为实际执行频率(每秒一次)
func main(){l := rate.NewLimiter(2, 10)ctx,cancel := context.WithCancel(context.Background())defer cancel()f:= func(ctx context.Context) error{select {case <-ctx.Done():return ctx.Err()default:}time.Sleep(1*time.Second)return nil}start := time.Now()for i := 0; i < 20; i++ {err := l.Wait(ctx)if nil != err{fmt.Println(err)fmt.Println(time.Since(start))return}f(ctx)}fmt.Println(time.Since(start))}结果:20.0107691sWaitN用于判断是否可以同时执行n个事件 , 每次消耗n个令牌 。 如下例子的总时间算法为:(5*6-10)/2=10
import ("context""fmt""golang.org/x/time/rate""time")func main(){l := rate.NewLimiter(2, 10)ctx,cancel := context.WithCancel(context.Background())defer cancel()f:= func(ctx context.Context) error{select {case <-ctx.Done():return ctx.Err()default:}return nil}start := time.Now()for i := 0; i < 6; i++ {err := l.WaitN(ctx,5)if nil != err{fmt.Println(err)fmt.Println(time.Since(start))return}f(ctx)}fmt.Println(time.Since(start))}结果:10.0011304s读取yaml文件
假设yaml文件内容如下 , yaml文件中的每个首字母必须小写 。 PS:yaml文件中的所有字符建议都小写
scrapeInterval: 60endpoints:- endpoint: cn-shanghai.log.aliyuncs.comaccessKeyID: LTAI2KSu0MDauu2raccessKeySecret: D3m0j7vDmrAWf33SFUh3LJRF1QGgTuproject: avacar-slb-slslogstore: avacar-slsconsumerGroupName: endCursorconsumerName: endConsumer1cursorPosition: END_CURSOR在代码中定义对应的解析结构体 , 结构体成员首字母大写 , 注意每个元素后面的yaml对应的字符串需要与yaml文件中的元素对应 , 大小写一致 。
type Config struct {ScrapeInterval int32Endpoints []Endpoints`yaml: "endpoints"`}type Endpoints struct {Endpoint string `yaml:"endpoint"`AccessKeyID string `yaml:"accessKeyID"`AccessKeySecret string `yaml:"accessKeySecret"`Project string `yaml:"project"`Logstore string `yaml:"logstore"`ConsumerGroupName string `yaml:"consumerGroupName"`ConsumerName string `yaml:"consumerName"`CursorPosition string `yaml:"cursorPosition"`}使用如下方式即可将yaml文件的内容提取出来 , 即config
var config ConfigconfigContent, err := ioutil.ReadFile("D:\\test.yaml")if err != nil {log.Panic("open file failed")return}yaml.Unmarshal(configContent, i < b.N; i++ {for j := 0; j < 10000; j++ {s = pool.Get().(*S)s.num = 1s.num++pool.Put(s)}}}func BenchmarkWithNoPool(b *testing.B) {var s *Sfor i := 0; i < b.N; i++ {for j := 0; j < 10000; j++ {s = &S{num: 1}s.num++}}}func main(){t1 := time.Now().Nanosecond()BenchmarkWithPool(&testing.B{N:10})t2 := time.Now().Nanosecond() - t1fmt.Println("t2 =",t2)t3 := time.Now().Nanosecond()BenchmarkWithNoPool(&testing.B{N:10})t4 := time.Now().Nanosecond() - t3fmt.Println("t4 =",t4)}}结果:
t2 = 1992800t4 = 999000
从下面可以看出 , put和get是按照顺序一对一的 , 如果get完 , 则调用New函数创建一个新的元素返回
// 建立对象var pipe = &sync.Pool{New:func()interface{}{return "Hello,BeiJing"}}// 放入pipe.Put("Hello,World1")pipe.Put("Hello,World2")pipe.Put("Hello,World3")// 取出log.Println(pipe.Get())log.Println(pipe.Get())log.Println(pipe.Get())// 再取就没有了,会自动调用NEWlog.Println(pipe.Get())结果:
2019/12/02 15:24:47 Hello,World12019/12/02 15:24:47 Hello,World22019/12/02 15:24:47 Hello,World32019/12/02 15:24:47 Hello,BeiJing
参考:
作者: charlieroro
出处: