QPS 滑动窗口限流
AI 推理网关要做秒级 QPS 限流 :每个请求带毫秒时间戳(升序),滑动窗口大小为 windowMs,窗口内最多放行 allow 个请求,超出则拒绝。给定升序请求时间戳数组,返回可放行的请求数。
输入
timestamps[] int64:请求时间戳数组(升序,单位:毫秒)windowMs int64:滑动窗口大小allow int:窗口内最多允许放行的请求数
输出
可放行请求数。
示例
输入:
timestamps = [100,150,200,500,600]
windowMs = 300
allow = 2
输出:
4
示例解释
t=100:放行(窗口内 1 个)t=150:放行(窗口内 2 个)t=200:窗口内已有 2 个请求,拒绝t=500:旧请求过期弹出,放行t=600:放行
共放行 4 个请求。
QPS 限流和并发限流
假设服务器规定:
- 300 毫秒内最多放行 2 个请求。
- 每个请求的处理时间是 50 毫秒。
请求到达时间:
t = 100:请求 A 到达
t = 150:请求 B 到达
t = 200:请求 C 到达
情况一:QPS 限流(本题)
t = 100:A 放行
t = 150:A 处理完成,B 放行
t = 200:B 处理完成,C 拒绝
尽管 A、B 都已经处理完成,但在当前的 300 毫秒窗口内,已经放行了 2 个请求。
因此,C 仍然会被拒绝。
情况二:并发数限制
假设最多允许 2 个请求同时执行。
t = 100:A 开始执行,并发数 = 1
t = 150:A 完成,B 开始执行,并发数 = 1
t = 200:B 完成,C 开始执行,并发数 = 1
由于请求处理完成会释放并发名额,因此三个请求都可以执行。
代码
cpp
#include <deque>
#include <vector>
#include <iostream>
#include <cstdint>
using namespace std;
// qps 滑动窗口限流算法
// O(n) + O(min(n,allow)
int solve(vector<uint64_t> ×tamps, uint64_t windowMs, int allow) {
int ans = 0;
deque<uint64_t> q;
for(uint64_t t : timestamps) {
while(!q.empty() && t - q.front() >= windowMs) q.pop_front();
if((int)q.size() < allow) {
q.push_back(t);
++ ans;
}
}
return ans;
}
int main()
{
vector<uint64_t> timestamps{100, 150, 200, 500, 600};
uint64_t windowMs = 200;
int allow = 2;
int ans = solve(timestamps, windowMs, allow);
cout << ans << endl;
return 0;
}