3

我刚刚切换到在 Heroku 上使用 Sidekiq,但在我的工作运行一段时间后,我得到了以下信息:

2012-12-11T09:53:07+00:00 heroku[worker.1]: Process running mem=1037M(202.6%)
2012-12-11T09:53:07+00:00 heroku[worker.1]: Error R14 (Memory quota exceeded)
2012-12-11T09:53:28+00:00 heroku[worker.1]: Error R14 (Memory quota exceeded)
2012-12-11T09:53:28+00:00 heroku[worker.1]: Process running mem=1044M(203.9%)

它一直这样增长。

对于这些工作,我使用 Nokogiri 和 HTTParty 来检索 URL 并解析它们。我尝试过更改一些代码,但我实际上并不确定我首先要寻找什么。我应该如何调试这个?

我尝试将 New Relic 添加到我的应用程序中,但不幸的是它还不支持 Sidekiq。

此外,在谷歌搜索之后,我试图切换到 SAX 解析器并查看它是否有效,但我被卡住了。这是我到目前为止所做的:

class LinkParser < Nokogiri::XML::SAX::Document
  def start_element(name, attrs = [])
    if name == 'a'
      puts Hash[attrs]['href']
    end
  end
end

然后我尝试类似:

page = HTTParty.get("http://site.com")
parser = Nokogiri::XML::SAX::Parser.new(LinkParser.new)

然后,我尝试对使用 HTTParty 检索到的数据使用以下方法,但无法使这些方法中的任何一个正常工作:

 parser.parse(File.read(ARGV[0], 'rb'))
 parser.parse_file(filename, encoding = 'UTF-8')
 parser.parse_memory(data, encoding = 'UTF-8') 

更新

我发现解析器不起作用,因为我正在调用parser.parse(page)而不是parser.parse(page.body) 但是我尝试使用上述脚本打印出各种网站的所有 html 标签,对于某些网站它打印出所有标签,而对于其他网站它只打印出几个标签。

如果我使用它Nokogiri::HTML()代替parser.parse()它工作正常。

我使用Nokogiri::XML::SAX::Parser.new()而不是Nokogiri::HTML::SAX::Parser.new()HTML 文档,这就是我遇到麻烦的原因。

代码更新

好的,我现在可以使用以下代码,但不知道如何将我得到的数据放入一个数组中,以便以后使用...

require 'nokogiri'

class LinkParser < Nokogiri::XML::SAX::Document
  attr_accessor :link

  def initialize
    @link = false
  end

  def start_element(name, attrs = [])
    url = Hash[attrs]
    if name == 'a' && url['href'] && url['href'].starts_with?("http")
      @link = true 
      puts url['href']
      puts url['rel']
    end
  end

  def characters(anchor)
    puts anchor if @link
  end

  def end_element(name)
    @link = false
  end

  def self.starts_with?(prefix)
    prefix.respond_to?(:to_str) && self[0, prefix.length] == prefix
  end
end
4

2 回答 2

5

最后,我发现内存泄漏是由于“Typhoeus”gem造成的,它是我在部分代码中使用的“PageRankr”gem 的依赖项。

我通过在本地运行代码并使用 监控内存使用情况来发现这一点watch "ps u -C ruby",然后测试代码的不同部分,直到我可以查明内存泄漏的来源。

我将此标记为已接受的答案,因为在原始问题中我不知道如何调试内存泄漏,但有人告诉我执行上述操作并且它有效。

于 2012-12-16T04:43:13.040 回答
0

以防万一您无法解决 gems 内存泄漏问题:

您可以在分叉中运行 sidekiq 作业,如答案https://stackoverflow.com/a/1076445/3675705中所述

只需添加应用程序助手“do_in_child”,然后在您的工作人员中

 def perform
   do_in_child do
     # some polluted task
   end
 end

是的,我知道这是一种肮脏的解决方案,因为 Sidekiq 应该在线程中工作,但在我的情况下,它是唯一一个用于生产的快速解决方案,因为我在通过 nokogiri 解析大型 XML 文件时工作速度很慢。

“快速”线程功能不会带来任何优势,但在 10 分钟的工作后,内存泄漏给了我一个 2GB+ 的主要 sidekiq 进程。一天后,sidekiq 虚拟内存增长到 11GB(我服务器上所有可用的虚拟内存),所有任务都变得非常缓慢。

于 2015-03-04T06:17:27.137 回答