Ruby 将多个请求以线程方式发布到同一url

Ruby 将多个请求以线程方式发布到同一url,ruby,multithreading,parallel-processing,faraday,typhoeus,Ruby,Multithreading,Parallel Processing,Faraday,Typhoeus,我构建了一个json块,如下所示: data = { "url" : "http://www.example.com/post", "postdata" : [ { "key1" : "value1" }, { "key2" : "value2" }, { "key3" : "value3" }, { "key4" : "value4" }, { "key5" : "value5" },

我构建了一个json块,如下所示:

data = {
    "url" : "http://www.example.com/post",
    "postdata" : [
        { "key1" : "value1" },
        { "key2" : "value2" },
        { "key3" : "value3" },
        { "key4" : "value4" },
        { "key5" : "value5" },
        { "key6" : "value6" }
    ]
}
我试图将“postdata”中的每个块并行发布,比如说将2个池发布到同一个“url”。我曾尝试使用法拉第、泰弗斯和并行,但在这样做的过程中,我没有遇到一个有效的用例

理想情况下,我希望使用typhous::Hydra或Faraday,将“data”对象传递给它,并使用data['url']作为端点在数据['postdata']上进行池化,但我空手而归。大多数情况下,我会遇到需要一个数据数组的情况,如:

[
    { "url" : "http://...",
      "data" : { "key1" : "value1" },
    { "url" : "http://...",
      "data" : { "key2" : "value2" },
    { "url" : "http://...",
      "data" : { "key3" : "value3" }
]
但我显然希望避免这种重复

最终目标:将可能有100个json主体并行地发布到同一个url,一次只共享10个。有人能帮我指引正确的道路吗

免责声明:这是一个内部端点,因此没有恶意

基于tadman的解决方案:

class BatchWrapper
  def initialize(data, offset)
    @data = data
    @offset = offset
  end

  def as_json
    @data['postdata'][@offset]
  end
end

q = Queue.new

data['postdata'].each_index do |i|
  q << BatchWrapper.new(data, i)
end

t = Thread.new do
  n = q.size
  n.times do |i|
    value = q.pop
    res = http.post(data['url'], value.as_json)
    puts res
    puts "consumed #{value.as_json}"
  end
end

t.join

通常的策略是,将源数据重新映射为更易于消化的内容,然后通过多个工作线程或某种异步事件驱动方法(如在EventMachine中使用的方法)将其拆分

线程更容易理解,然后您可以使用该结构为每个要使用的线程批处理工作

将作业分解为一系列对象,将这些对象塞入队列,然后旋转N个线程来处理这些队列

因为您使用的是线程,所以可以使用共享数据。例如,您可以拥有一个瘦包装器对象,给定该格式的结构,该对象将捕获您正在发送的偏移量:

class BatchWrapper
  def initialize(data, offset)
    @data = data
    @offset = offset
  end

  def as_json
    @data['postdata'][@offset]
  end
end
然后,针对您打算提出的每个请求,只需填充其中一个对象:

q = Queue.new

data['postdata'].each_index do |i|
  q << BatchWrapper.new(data, i)
end

包装器方法允许您准确地组合从主对象共享的数据和特定于请求的数据,并对数据本身进行任何必要的重构。as_json方法返回to_json方法最终编码的内容,因此您可以完全控制它。

谢谢您。详细说明后,我得到了一个t=Thread.new do的内部,如下所示:n=q.size;n、 时代确实如此;值=q.pop;res=reqdata['url'],value.as_json;puts-res似乎已经工作了,因为它在每次迭代中输出索引1,并且每个json块值。as_json。在一般代码中,队列大小可能会随时间变化,因此最好不要依赖于任何特定的长度。一个简单的方法是在完成工作后杀死所有工人,在其中注入N个表示停止处理并将线程从循环中断开的作业。
Thread.new do
  while (wrapper = q.pop)
    # Send it...
    make_request(wrapper.to_json)
  end
end