1

我有一个填充了可能有很多记录的数组。每条记录都应由服务器保存在 RESTful RecordsController 中。我目前的解决方案如下所示:

def self.send! options = nil
  records = fetch_records
  records.each do |r|
    send_data!(r) ? records = records.delete_if{|rec| rec == r } : break
  end
  storage.save! records

  true
end

private

def self.send_data! record, options = nil
  begin
    response = Net::HTTP.Proxy(configuration.proxy_host, configuration.proxy_port).start(configuration.host, configuration.port) do |http|
      request = Net::HTTP::Post.new(request_path options)
      request.body = record.to_json
      http.request request
    end
    raise StandardError unless response.code == "200"
  rescue Exception => e
    return false
  end

  true
end

该解决方案的优点是,如果发生 ConnectionError、ConnectionTimeout 或 ServerError,未发送的记录将存储在本地,以后可以再次提交。匹配的控制器是一个标准的 Rails 控制器。

我现在的问题是,在生产模式下这似乎很慢。服务器不是瓶颈的地方大约是 4 个请求/秒。

现在的问题是,它是否有助于只实例化 HTTP 客户端一次并使用同一连接发送所有记录。我没有找到实现它的解决方案,因为我需要这里代码的 save_or_store 行为。

另一种解决方案可能不是一个接一个地传输完成的记录,而是将它们分组并创建一个新的控制器,该控制器接受我的记录组来存储它们。

所以这个问题归结为一个更具架构性的问题,而不是技术问题。无论哪种方式,我都想知道我是否可以保持 HTTP 连接打开并以这种方式加速我的解决方案。

有任何想法吗?

问候菲利克斯

4

2 回答 2

2

切换到em-http-request- 基于 EventMachine 的 HTTP 客户端 - 并使用其 Multi 接口同时发送多个请求可能会提高您的吞吐量。

但是更好的 HTTP 客户端的好处是微不足道的。由于您不对从控制器获得的 HTTP 响应做任何事情——这意味着您没有使用 HTTP 作为应用程序协议——解决问题的最佳方法是实际发送整个 Array 以在服务器端进行处理. 毕竟,您不必为每条记录都发出一次请求而付出代价。

最终,如果您愿意,最好公开一个带有处理失败的记录列表的 URI,这样您就可以根据自己的意愿重新提交或直接忽略。

我会将MessagePack加入其中,以序列化 Array 并减小有效负载的大小并加快消息交换。

于 2011-10-04T03:10:36.753 回答
0

如果我正在阅读发送!方法正确,您正在遍历每条记录,并且在该循环中只是从数组中删除当前记录并发送其他所有内容?为了节省计算方面的工作量,请使用 Array 类的 delete() 方法而不是 delete_if。

def self.send! options = nil
  records = fetch_records
  records.each do |r|
    if send_data!(r)
      records.delete(r)
    else
      break
    end
  end
  storage.save! records

  true
end

虽然我不确定你在哪里传递 send_data 的记录参数!方法。由于 terinary 将使用该方法的结果。

Net http 可能需要一些时间来处理它的所有请求。我知道当我运行几百个 URL 来检查他们的响应代码时,需要 5-10 分钟才能完成。我自己用的不多,看一下:https ://github.com/jnunemaker/httparty 。也许它会更好地为你工作。

于 2011-09-29T12:08:33.220 回答