运行 内存不足 XML SOAP 响应在 Rails 中与 Savon 和 Nokogiri
Running out of memory parsing XML SOAP response in Rails with Savon and Nokogiri
我有一个使用 SOAP 网络服务端点的 rails 4 网络应用程序。对于每家公司,发送请求以获取资源列表(不管是什么类型,只是信息)。
该方法使用 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. 以上的 None 是可能的,我只能增加我系统的 RAM?我有一个 4GB 的亚马逊 AWS 实例。
我只是想解释一下我是如何解决它的以及我的见解。解析大 XML 文件时,最好的方法可能是使用 SAX 解析器,这是@dbugger 建议的注释。它不会将整个 XML 加载到内存中,这就是它解决问题的原因。但是,就我而言,有两个不便之处。首先,性能对我们来说至关重要,SAX 解析器比 DOM 解析器慢。第二个是我们已经有了带有 DOM 解析器的所有代码,我们需要重新开发所有内容。
出于这些原因,我的方法是一种绕行方法。我只是将大的 XML 文件分成更小的部分,以便 DOM 解析器更容易处理。
目前,它工作正常。所以,它看起来工作。如果我发现任何问题,我会在这里更新。
我有一个使用 SOAP 网络服务端点的 rails 4 网络应用程序。对于每家公司,发送请求以获取资源列表(不管是什么类型,只是信息)。
该方法使用 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. 以上的 None 是可能的,我只能增加我系统的 RAM?我有一个 4GB 的亚马逊 AWS 实例。
我只是想解释一下我是如何解决它的以及我的见解。解析大 XML 文件时,最好的方法可能是使用 SAX 解析器,这是@dbugger 建议的注释。它不会将整个 XML 加载到内存中,这就是它解决问题的原因。但是,就我而言,有两个不便之处。首先,性能对我们来说至关重要,SAX 解析器比 DOM 解析器慢。第二个是我们已经有了带有 DOM 解析器的所有代码,我们需要重新开发所有内容。
出于这些原因,我的方法是一种绕行方法。我只是将大的 XML 文件分成更小的部分,以便 DOM 解析器更容易处理。
目前,它工作正常。所以,它看起来工作。如果我发现任何问题,我会在这里更新。