代码拉取完成,页面将自动刷新
/**
* Tencent is pleased to support the open source community by making polaris-go available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
// Package common .
package common
import (
"sync"
"sync/atomic"
)
// NewSlidingWindow 创建滑窗
func NewSlidingWindow(slideCount int, intervalMs int) *SlidingWindow {
slidingWindow := &SlidingWindow{}
slidingWindow.intervalMs = intervalMs
slidingWindow.slideCount = slideCount
slidingWindow.mutex = &sync.Mutex{}
slidingWindow.windowLengthMs = intervalMs / slideCount
slidingWindow.windowArray = make([]*Window, slideCount)
for i := 0; i < slideCount; i++ {
slidingWindow.windowArray[i] = &Window{}
}
return slidingWindow
}
// calculateWindowStart 计算起始滑窗
func (s *SlidingWindow) calculateWindowStart(curTimeMs int64) int64 {
return CalculateStartTimeMilli(curTimeMs, int64(s.windowLengthMs))
}
// CalculateStartTimeMilli 计算起始滑窗
func CalculateStartTimeMilli(curTimeMs int64, interval int64) int64 {
return curTimeMs - curTimeMs%interval
}
// calculateTimeIdx 计算时间下标
func (s *SlidingWindow) calculateTimeIdx(curTimeMs int64) int {
timeId := curTimeMs / int64(s.windowLengthMs)
return int(timeId % int64(s.slideCount))
}
// currentWindow 当前窗口
func (s *SlidingWindow) currentWindow(curTimeMs int64, reset bool) (*Window, *Window) {
idx := s.calculateTimeIdx(curTimeMs)
windowStart := s.calculateWindowStart(curTimeMs)
oldWindow := s.windowArray[idx]
oldWindowStart := atomic.LoadInt64(&oldWindow.WindowStart)
if oldWindowStart == windowStart {
return oldWindow, nil
} else if !reset {
return nil, nil
} else {
s.mutex.Lock()
expiredWindow := oldWindow.reset(oldWindowStart, windowStart)
s.mutex.Unlock()
return oldWindow, expiredWindow
}
}
// AddAndGetCurrentPassed 原子增加,并返回当前bucket
func (s *SlidingWindow) AddAndGetCurrentPassed(curTimeMs int64, value uint32) (uint32, *Window) {
window, expiredWindow := s.currentWindow(curTimeMs, true)
return window.addAndGetPassed(value), expiredWindow
}
// AddAndGetCurrentLimited 原子增加,并返回当前bucket
func (s *SlidingWindow) AddAndGetCurrentLimited(curTimeMs int64, value uint32) (uint32, *Window) {
window, expiredWindow := s.currentWindow(curTimeMs, true)
return window.addAndGetLimited(value), expiredWindow
}
// AcquireCurrentValues 获取上报数据
func (s *SlidingWindow) AcquireCurrentValues(curTimeMs int64) (uint32, uint32, *Window) {
window, expiredWindow := s.currentWindow(curTimeMs, true)
passed := window.swapPassed()
limited := window.swapLimited()
return passed, limited, expiredWindow
}
// TouchCurrentPassed 获取上报数据
func (s *SlidingWindow) TouchCurrentPassed(curTimeMs int64) (uint32, *Window) {
window, expiredWindow := s.currentWindow(curTimeMs, true)
passed := window.addAndGetPassed(0)
return passed, expiredWindow
}
// SlidingWindow 滑窗通用实现
type SlidingWindow struct {
// 单个窗口长度
windowLengthMs int
// 所有窗口总长度
intervalMs int
// 更新锁
mutex *sync.Mutex
// 滑窗列表
windowArray []*Window
// 滑窗数
slideCount int
}
// reset 重置窗口,返回过期的窗口
func (w *Window) reset(oldWindowStart int64, windowStart int64) *Window {
if atomic.CompareAndSwapInt64(&w.WindowStart, oldWindowStart, windowStart) {
passedValue := atomic.SwapUint32(&w.PassedValue, 0)
limitedValue := atomic.SwapUint32(&w.LimitedValue, 0)
return &Window{
WindowStart: oldWindowStart,
PassedValue: passedValue,
LimitedValue: limitedValue,
}
}
return nil
}
// Window 单个窗口
type Window struct {
// 起始时间
WindowStart int64
// 通过数
PassedValue uint32
// 被限流数
LimitedValue uint32
}
// addAndGetPassed 原子增加通过数
func (w *Window) addAndGetPassed(value uint32) uint32 {
return atomic.AddUint32(&w.PassedValue, value)
}
// addAndGetLimited 原子增加被限流数
func (w *Window) addAndGetLimited(value uint32) uint32 {
return atomic.AddUint32(&w.LimitedValue, value)
}
// swapPassed 原子增加通过数
func (w *Window) swapPassed() uint32 {
return atomic.SwapUint32(&w.PassedValue, 0)
}
// swapLimited 原子增加被限流数
func (w *Window) swapLimited() uint32 {
return atomic.SwapUint32(&w.LimitedValue, 0)
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。