我有一个填充了大量记录的数组。每个记录都应由服务器保存在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连接打开并以这种方式加速我的解决方案。
有什么想法吗?
此致 菲利克斯
答案 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。也许它会对你更好。