• 使用滑动窗口统计访问频次,进行限流


    如题

    package slidingwindow
    
    import (
    	"errors"
    	"sync"
    	"time"
    )
    
    // Window window
    type Window struct {
    	sync.RWMutex
    
    	window   time.Duration
    	tick     time.Duration
    	samples  []int64
    	stopOnce sync.Once
    	stopping chan struct{}
    	pos      int
    	size     int
    }
    
    // New new window
    // New(time.Second*5, time.Second)
    func New(window, tick time.Duration) (*Window, error) {
    	if window == 0 {
    		return nil, errors.New("sliding window cannot be zero")
    	}
    
    	if tick == 0 {
    		return nil, errors.New("tick cannot be zero")
    	}
    
    	if window <= tick || window%tick != 0 {
    		return nil, errors.New("window size has to be a multiplier of granularity size")
    	}
    
    	win := &Window{
    		window:   window,
    		tick:     tick,
    		samples:  make([]int64, int(window/tick)),
    		stopping: make(chan struct{}, 1),
    	}
    
    	go win.shifter()
    
    	return win, nil
    }
    
    func (win *Window) shifter() {
    	ticker := time.NewTicker(win.tick)
    
    	for {
    		select {
    		case <-ticker.C:
    			win.slidingWindow()
    		case <-win.stopping:
    			return
    		}
    	}
    }
    
    func (win *Window) slidingWindow() {
    	win.Lock()
    	defer win.Unlock()
    
    	win.pos = win.pos + 1
    	if win.pos >= len(win.samples) {
    		win.pos = 0
    	}
    	win.samples[win.pos] = 0
    }
    
    // Add increments the value of the current sample.
    func (win *Window) Add() {
    	win.Lock()
    	defer win.Unlock()
    	win.samples[win.pos]++
    }
    
    // AddCount increments the value of the current sample.
    func (win *Window) AddCount(n int64) {
    	win.Lock()
    	defer win.Unlock()
    	win.samples[win.pos] += n
    }
    
    // Reset the samples in this sliding time window.
    func (win *Window) Reset() {
    	win.Lock()
    	defer win.Unlock()
    
    	win.pos, win.size = 0, 0
    	for i := range win.samples {
    		win.samples[i] = 0
    	}
    }
    
    // Total returns the sum of all values over the window
    func (win *Window) Total() int64 {
    
    	win.RLock()
    	defer win.RUnlock()
    
    	var total int64
    	for i := range win.samples {
    		total += win.samples[i]
    	}
    	return total
    }
    
    // Stop the shifter of this sliding time window. A stopped SlidingWindow cannot
    // be started again.
    func (win *Window) Stop() {
    	win.stopOnce.Do(func() {
    		win.stopping <- struct{}{}
    	})
    }
    
    
  • 相关阅读:
    想做的事情
    js学习笔记2(5章操作方法)
    js学习笔记1(变量、作用域、内存)
    输入框去除默认的文字,jquery方法
    同类型元素,只有一个被选中js
    淘宝分类常见---部分显示和全部显示的js效果
    关于游戏提名信息项目的总结
    20174310隋润起网络对抗免考报告
    2019-2020-2 20174310 隋润起《网络对抗技术》Exp9 Web安全基础
    2019-2020-2 20174310隋润起《网络对抗技术》Exp8 Web基础
  • 原文地址:https://www.cnblogs.com/warrior/p/12101792.html
Copyright © 2020-2023  润新知