这个问题不仅仅是关于红宝石的。
我有很多工作正在运行以创建许多与外部API的连接。此API有一个限制 现在我使用sidekiq和redis来限制访问 即在每次访问API时,我都会运行工作人员 然后工作人员启动它检查上次访问API的时间,如果早于该API允许,则重新安排工作人员,否则在redis中触摸时间并运行请求。
例如:
def run_or_schedule
limiter = RedisLimiter.new(account_token)
if limiter.can_i_run?
limiter.like
run
else
ApiWorker.perform_at(limiter.next_like, *params)
end
end
问题是我创建了很多请求,并且他们多次重新安排。
也许有人可以推荐更好的解决方案吗?
也许存在任何设计模式?
答案 0 :(得分:1)
您使用的轮询方法的一种替代方法是拥有supervisor
。
因此,不是让每个工作人员自己处理问题,而是让另一个对象/工人/进程决定下一个工作人员何时运行。
如果API在请求之间设置了时间限制,您可以让此主管在时间限制允许的情况下执行。
如果限制更复杂(例如,每X间隔的请求总数),您可以让主管持续运行并且在达到该间隔量的限制块(休眠)时运行。恢复后,它可以从队列中继续下一个工作人员。
这种方法的一个明显优势是,您可以跳过与实例化的每个单独工作人员相关的开销,检查自己是否应该运行,并且如果不应该重新安排。
答案 1 :(得分:1)
您可以使用一个队列,以及一个以允许的最大速率发送事件(等待时)的专用线程。
假设您可以每秒发送一个API调用,您可以执行以下操作:
class APIProxy
def like(data)
@like_queue << data
end
def run
Thread.new do
@like_queue = Queue.new
loop do
actual_send_like @like_queue.pop
sleep 1
end
end
end
private
def actual_send_like(data)
# use the API you need
end
end