【问题标题】:Running out of memory parsing XML SOAP response in Rails with Savon and Nokogiri使用 Savon 和 Nokogiri 在 Rails 中解析 XML SOAP 响应时内存不足
【发布时间】: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


【解决方案1】:

我只想解释一下我是如何解决它的以及我的见解。解析大型 XML 文件时,最好的方法可能是使用 SAX 解析器,这是@dbugger 建议的注释。它不会将整个 XML 加载到内存中,这就是它解决问题的原因。但是,就我而言,有两个不便之处。首先,性能对我们来说很重要,而且 SAX 解析器比 DOM 解析器慢。第二个是我们已经有了 DOM 解析器的所有代码,我们需要重新开发一切。

出于这些原因,我的方法是一种绕行。我只是将大 XML 文件拆分成更小的部分,以便 DOM 解析器更轻松地处理。

目前,它运行良好。所以,它看起来有效。如果我发现任何问题,我会在这里更新。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多