Java 当元素列表达到其配额时要阻止的数据结构

Java 当元素列表达到其配额时要阻止的数据结构,java,ratelimit,Java,Ratelimit,我有一个“键”,可以让我每分钟调用rest端点500次(每个键可以是200、300或500) 当密钥在1分钟内达到其配额(1分钟桶不是滑动窗口)时,端点返回一个429(速率限制),并有等待延迟。一旦延迟过去,我可以再次使用这把钥匙 My API是一种代理(客户端调用My API,My API通过提供一个密钥调用其他服务) 我的API将堆叠所有用户密钥,以便在某种意义上成为一个大密钥。 当“任意”客户端调用我的api时,我的系统会巧妙地选择一个仍然有配额的密钥,当该密钥达到配额时,它会将其从可用密

我有一个“键”,可以让我每分钟调用rest端点500次(每个键可以是200、300或500) 当密钥在1分钟内达到其配额(1分钟桶不是滑动窗口)时,端点返回一个429(速率限制),并有等待延迟。一旦延迟过去,我可以再次使用这把钥匙

My API是一种代理(客户端调用My API,My API通过提供一个密钥调用其他服务) 我的API将堆叠所有用户密钥,以便在某种意义上成为一个大密钥。 当“任意”客户端调用我的api时,我的系统会巧妙地选择一个仍然有配额的密钥,当该密钥达到配额时,它会将其从可用密钥列表、队列或任何结构中删除

我很难为它选择一个好的数据结构和逻辑。我的想法是这样的

1) 获取一个仍有配额且至少有一个剩余呼叫可用的密钥-1a)如果没有可用的密钥,只需“等待”直到有一个可用

2) 调用端点

3) 将密钥配额减少为1,如果密钥受到速率限制,则将其从“队列”或“列表”或其他任何位置删除

4) 回到1

请注意,我的API调用的端点返回有用的信息,如“requestRemaining”,该信息指示密钥在受到速率限制之前还有多少请求。“速率延迟”,指示密钥在速率受限的情况下可以再次使用的时间

我认为一个很好的解决方案是积极主动地知道什么时候一个密钥会受到速率限制,而不是仅仅依赖端点响应。这样,我们就避免了使用已达到配额的密钥对端点进行“免费”调用

我已经尝试过使用DelayQueue和一些信号量来阻止没有可用密钥的情况,但我有一个问题,即事先知道密钥是否会受到速率限制。 我希望在“请求”级别而不是关键级别并发。这意味着我不希望客户端在发出请求之前锁定密钥。如果一个密钥的配额为500,我希望在最大500个并发客户端上使用一个密钥


我希望有经验更丰富的人能为我提供帮助。

如果你不介意阻止一个键,你可以拥有一个延迟的键队列,如果getDelay()是该键的速率限制时间(如果该键仍在配额中,则为0)

您在使用密钥之前移除该密钥将避免其他人使用该密钥。在“最终关闭”中,您总是将键放回原处,多亏了DelayQeeue,该键只有在达到延迟时才能由.take()使用


编辑:抱歉,刚才看到您编辑了问题,使其出现在请求上而不是键上。那样的话。。。我不确定,但我很好奇其他人会如何处理这个有趣的问题。今天晚些时候我可能会试着打一针,只是为了好玩,没有任何好处
private void executeRequest(...) {
 long delay = 0L
 try {
  // .take from the queue (it will remove it from the queue)
  // execute your request
  // if you get 429 take the delay from the response header
 } finally {
  //put back the key in the queue but setting the "delay" (0 or whatever the header had
 }

}