【发布时间】:2019-03-10 18:15:31
【问题描述】:
我有一个使用 SOAP 网络服务端点的 rails 4 webapp。对于每家公司,发送一个请求以获取资源列表(不管是什么类型,只是信息)。
该方法使用 Savon 2 发送请求,获取响应并使用 Nokogiri 解析它以使用 xpath 处理 XML 资源。
这个循环一直很好,直到它试图让一家拥有大量资源的特定公司,远远超过其他公司。然后,问题来了。我在 ubuntu 中使用“top”进行了监控,当进程开始处理响应时,进程会消耗 RAM 内存,直到它杀死 rails 应用程序。然后内存被释放,但 webapp 下来了。
请在方法中找到示例代码:
# Initializing Savon client
client = Savon.client(wsdl: endpoint,
log_level: :info,
log: true,
pretty_print_xml: true,
open_timeout: 300,
read_timeout: 300)
for company in companies do
message = {'in0' => USER_ID,
'in1' => USERNAME,
'in2' => MMK_PASSWORD,
'in3' => company.id}
@logger.debug "getResources=1"
response = client.call(:get_resources, message: message)
@logger.debug "getResources=2"
resourcesXML = response.to_hash[:get_resources_response][:out]
@logger.debug "getResources=3"
resourcesParsed = Nokogiri::XML(resourcesXML)
@logger.info "getResources=4"
resources = resourcesParsed.xpath("//resource")
@logger.info "getResources=5"
日志显示为“getResources=3”。然后 webapp 崩溃了。
您认为最好的方法是什么? 1.有没有更好的方法来处理这些信息避免杀死应用程序。 2.也许有办法部分处理响应? 3. 这个场景有更好的性能工具吗? 4.以上都不可能,我只能增加系统的RAM?我有一个 4GB 的 Amazon AWS 实例。
【问题讨论】:
-
不要使用 DOM 解析,而是使用不需要加载整个文档的 SAX 解析器。 Nokogiri 有一个 XML 阅读器,可让您执行此操作。这是一个快速概览的链接viget.com/articles/parsing-big-xml-files-with-nokogiri
-
我会联系负责该 API 端点的人,因为这太荒谬了。
-
感谢您的回答。 Pguardiario 虽然它会很棒,但不幸的是,向 API 负责人抱怨不是一种选择。 @dbugger 我一直在阅读有关 SAX 解析器的信息(直到现在我一直使用 dom)。当然,这可能是一种方法,但我发现有两个不便之处: 1. 我必须重新开发所有的解析代码,因为它完全不同。 2. DOM 解析器速度较慢,我无法使用 xpath 获取特定路径,我需要迭代整个 XML。所以,如果可能的话,我想把它作为最后的方法。您认为可以将 XML 响应拆分为多个 XML 吗?
-
1.是的。 2. 是的,这就是权衡。 3. 这是一个 API 问题。
-
关于您的回答 3. 您是指 SAX 还是第 3 方数据提供商?您如何看待我富有想象力的方法。我的意思是以某种方式将 XML 响应拆分为几个部分,以处理足够小的 XML 以避免内存问题。
标签: ruby-on-rails ruby soap nokogiri savon