Fix: overload_control/flow_control:smooth_limiter issues related to accuracy and efficiency #185#186
Open
AntiBargu wants to merge 5 commits intotrpc-group:mainfrom
Open
Fix: overload_control/flow_control:smooth_limiter issues related to accuracy and efficiency #185#186AntiBargu wants to merge 5 commits intotrpc-group:mainfrom
AntiBargu wants to merge 5 commits intotrpc-group:mainfrom
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
解决方案
通过引入
RecentQueue来实现滑动窗口算法。RecentQueue用来保存滑动窗口内最近所有活跃请求的时间戳。从实现上说,依然使用 ring queue,该队列的初始大小为 QPS(滑动窗口内能够保存连接的最大值)。不难看出,由于
RecentQueue保存时序,所以在RecentQueue内时间戳螺旋递增,RecentQueue是一个有序结构。在
RecentQueue中cur表示存放当前请求时间戳的位置。当新请求到达的时候,cur指示RecentQueue中缓存最久的时间戳。过滤请求
当一个请求到达的时候,该请求的时间戳为
now。当
now - 1s < RecentQueue[cur]时,说明当前RecentQueue已满,且缓存最久时间戳RecentQueue[cur]比较新,不能被淘汰,故应拒绝本次访问;当
now - 1s ≥ RecentQueue[cur]时,说明缓存最久时间戳RecentQueue[cur]缓存时间超过1s 可以被淘汰,故更新RecentQueue。流程的时间复杂度为O(1)。
求当前时刻滑动窗口内活跃请求总数
由于
RecentQueue具有螺旋递增的性质,其逻辑结构是一个有序结构,故能够通过二分查找找到第一个满足大于now - 1s的位置,与当前 cur 做偏移量计算即可得到当前时刻滑动窗口内活跃请求总数。流程的时间复杂度为O(logn)。
算法设计思想
惰性求值
这一点沿用了之前设计令牌桶算法时的思想。
建模——以缓存设计的角度解决滑动窗口问题
熟悉缓存策略的朋友应该不难看出这个算法有点像
LRU。RecentQueue和Least Recently Used稍有区别:RecentQueue缓存时间戳只访问/缓存一次;Least Recently Used缓存的对象可能被访问多次。访问次数的差异,造成了在底层数据结构选型的不同,LRU需要频繁插入、删除,故而使用双向链表结构,另外,为了提升LRU查找的能力,通常在LRU实现的时候维护 hash 表。RecentQueue有拒绝更新缓存的能力;相反,LRU没有。算法优点