Elixir 如何处理API的不同速率限制?
我为一个API构建了一个包装器,该API一直在工作,但现在该公司决定为其端点实施不同的速率限制,因为这是一个游戏,他们有服务器,每个服务器都有不同的限制,例如,EUW服务器有一个限制,而北美有另一个限制,但他们为他们的玩家提供相同的信息。现在,我实现了一个GenServer,它负责处理这些不同的速率限制,但我无法找到一种方法来处理开发人员密钥的速率限制,这些密钥是20r/1s或100r/2m。默认情况下,我实现了第一个限制,每秒20个请求,但这并不总是正确的。我用Exrate来处理这些请求 我希望完成的工作:一种处理开发关键点短期和长期限制的方法 在处理请求的函数中,我有一些我认为需要删除的东西,现在它只是一个占位符Elixir 如何处理API的不同速率限制?,elixir,Elixir,我为一个API构建了一个包装器,该API一直在工作,但现在该公司决定为其端点实施不同的速率限制,因为这是一个游戏,他们有服务器,每个服务器都有不同的限制,例如,EUW服务器有一个限制,而北美有另一个限制,但他们为他们的玩家提供相同的信息。现在,我实现了一个GenServer,它负责处理这些不同的速率限制,但我无法找到一种方法来处理开发人员密钥的速率限制,这些密钥是20r/1s或100r/2m。默认情况下,我实现了第一个限制,每秒20个请求,但这并不总是正确的。我用Exrate来处理这些请求 我希
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
每个区域可以保留两个计数器,一个用于每秒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
根据
区域的值计算时间
和金额
的值怎么样?例如,{time,amount}=案例区域do“US”->{1,2};“EUW”->{3,4}结束
并将其传递给ExRated
?@Dogbert哦,不,我已经这样做了,我将使用GenServer编辑答案,我所做的,我正在讨论开发密钥中的两种限制情况。有什么好的解决方案可以支持开发限制,即每秒20个请求或每2分钟100个请求。啊。像这样的怎么样<代码>大小写{ExRated.check_rate({region}-1,20,1),ExRated.check_rate({region}-2,100,120)}do{{:好的,{好的,{好的,{好的,{好的,}->。。。结束
。每次都会增加两个计数器,如果其中任何一个达到限制,您可以中止请求。嗯,我想我可以处理这个问题,让我看看我的想法@DogbertYes,我在你评论时使用了这个解决方案,谢谢!