RESTful Rails控制器和net / http作为客户端 - 许多请求都很慢

时间:2011-09-29 09:31:30

标签: ruby-on-rails ruby http net-http

我有一个填充了大量记录的数组。每个记录都应由服务器保存在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连接打开并以这种方式加速我的解决方案。

有什么想法吗?

此致 菲利克斯

2 个答案:

答案 0 :(得分:2)

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

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

最后,如果您愿意,最好公开一个带有未能处理的记录列表的URI,这样您就可以随意重新提交或者只是忽略。

我会在混合中抛出MessagePack,以序列化数组并减少有效负载的大小并加快消息交换。

答案 1 :(得分: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。也许它会对你更好。