我为正在运行的API构建了一个包装器,但现在该公司决定为其端点实施不同的速率限制,因为这是针对他们拥有服务器且每个服务器具有不同限制的游戏,例如,EUW服务器有一个限制,而北美有另一个,但他们为他们的玩家提供相同的信息。现在,我实现了一个GenServer来处理这些不同的速率限制,但我无法找到一种方法来处理20r / 1s或100r / 2m的开发人员密钥的速率限制。默认情况下,我实现了第一个限制,每秒20个请求,但并不总是如此。我使用ExRated来处理请求。
我希望完成的工作:一种处理开发密钥短期和长期限制的方法。
在执行请求的函数中,我有一些我认为我需要摆脱的东西,它现在只是一个占位符。
def get(region, rest, opt) do
url = Map.get(@endpoint, region)
if Mix.env() == :prod do # This part
# Enforcing the time and amount of requests per method if
# opts provided
opt_time = Keyword.get(opt, :time)
opt_amount = Keyword.get(opt, :amount)
region
|> ExRated.check_rate(opt_time, opt_amount)
|> parse(url, rest)
else
region
|> ExRated.check_rate(time(), amount())
|> parse(url, rest)
end
end
上面的else语句是我想要修复以支持两种开发限制的语句。
编辑根据第一条评论:
defmodule Godfist.LeagueRates do
@moduledoc false
# Handles checking the information passed and assigning the correct
# limit to the request.
use GenServer
alias Godfist.HTTP
# Rates for different servers.
@rates [
# "League" endpoints/servers
euw: {300, 60_000},
na: {270, 60_000},
eune: {135, 60_000},
br: {90, 60_000},
kr: {90, 60_000},
lan: {80, 60_000},
las: {80, 60_000},
tr: {60, 60_000},
oce: {55, 60_000},
jp: {35, 60_000},
ru: {35, 60_000},
# other endpoints
match: {500, 10_000},
matchlist: {1000, 10_000},
champion_masteries_runes: {400, 60_000},
static: {10, 3_600_000},
other: {20_000, 10_000}
]
# API
def start_link,
do: GenServer.start_link(__MODULE__, %{}, name: :league_limit)
def handle_rate(region, rest, endpoint \\ nil) do
GenServer.call(:league_limit, {:handle_rate, region, rest, endpoint})
end
# Server
def init(state),
do: {:ok, state}
# This first handler is matching on the "Leagues" endpoints,
# that's why endpoint is nil, that arg is meant to be used with
# the other endpoints (Matches, Runes, etc...)
def handle_call({:handle_rate, region, rest, endpoint}, _from, state)
when is_nil(endpoint) do
{time, amount} = Keyword.get(@rates, region)
{:reply, HTTP.get(region, rest, time: time, amount: amount), state}
end
def handle_call({:handle_rate, region, rest, endpoint}, _from, state) do
{time, amount} = Keyword.get(@rates, endpoint)
{:reply, HTTP.get(region, rest, time: time, amount: amount), state}
end
end
答案 0 :(得分:2)
每个区域可以保留两个计数器,一个用于每秒20个请求限制,一个用于每两分钟100个请求。在发送请求之前,您可以检查是否已达到其中一个限制,如果是,则中止发送请求。
case {ExRated.check_rate("#{region}-1", 20, 1), ExRated.check_rate("#{region}-2", 100, 120)} do
{{:ok, _}, {:ok, _}} ->
# neither limit has been hit
_ ->
# one or both limits have been hit
end