Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 具有限制的api并发访问_Ruby_Design Patterns_Concurrency_Sidekiq - Fatal编程技术网

Ruby 具有限制的api并发访问

Ruby 具有限制的api并发访问,ruby,design-patterns,concurrency,sidekiq,Ruby,Design Patterns,Concurrency,Sidekiq,这个问题不仅仅是关于ruby的 我有许多工人在运行,以创建许多到外部API的连接。此API有一个限制。 现在我使用sidekiq和redis来限制访问。 i、 e.每次访问API时,我都会运行worker。 然后工人开始检查最后一次访问API的时间,如果时间早于API允许的时间,工人将被重新调度,否则它将在redis中触摸时间并运行请求 例: 问题是,我创建了许多请求,它们多次被重新调度 也许有人能推荐一个更好的解决方案吗? 也许有任何设计模式可以实现这一点?除了使用轮询方法外,您还可以使用一个

这个问题不仅仅是关于ruby的

我有许多工人在运行,以创建许多到外部API的连接。此API有一个限制。
现在我使用sidekiq和redis来限制访问。
i、 e.每次访问API时,我都会运行worker。
然后工人开始检查最后一次访问API的时间,如果时间早于API允许的时间,工人将被重新调度,否则它将在redis中触摸时间并运行请求

例:

问题是,我创建了许多请求,它们多次被重新调度

也许有人能推荐一个更好的解决方案吗?


也许有任何设计模式可以实现这一点?

除了使用轮询方法外,您还可以使用一个
监督员

因此,您可以使用另一个对象/工作者/进程来决定下一个工作者何时运行,而不是让每个工作者自己处理问题

如果API在两个请求之间设置了时间限制,您可以让该主管在时间限制允许的情况下尽可能频繁地执行

如果限制更复杂(例如,每X个间隔的请求总数),您可以让主管持续运行,并在达到该间隔量的限制块(睡眠)时运行。恢复后,它可以与队列中的下一个工作进程一起继续


这种方法的一个明显优点是,您可以跳过与实例化每个工作进程相关的开销,检查它是否应该运行,如果不应该,则重新调度。您可以使用队列和专用线程,以允许的最大速率发送事件(当有任何等待时)

假设您可以每秒发送一个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
class代理
类def(数据)
@喜欢排队吗
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