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) ましたが、上記のスクリプトを使用してさまざまな Web サイトのすべての html タグを印刷しようとしましたが、一部のサイトではすべてのタグが印刷され、他のサイトでは印刷のみが行われましたいくつかのタグを出します。

Nokogiri::HTML()代わりに使用すると正常にparser.parse()動作します。

HTML ドキュメントNokogiri::XML::SAX::Parser.new()の代わりにを使用していたため、問題が発生していました。Nokogiri::HTML::SAX::Parser.new()

コードの更新

OK、次のコードが機能するようになりましたが、取得したデータを後で使用できる配列に入れる方法がわかりません...

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

最終的に、コードの一部で使用している「PageRankr」gem の依存関係である「Typhoeus」gemが原因でメモリ リークが発生することがわかりました。

これを発見したのは、コードを でメモリ使用量を監視しながらローカルで実行し、コードwatch "ps u -C ruby"のさまざまな部分をテストして、メモリ リークの原因を特定できるようにすることでした。

元の質問ではメモリリークをデバッグする方法がわからなかったので、これを受け入れられた回答としてマークしていますが、誰かが上記のことをするように言ったのでうまくいきました。

于 2012-12-16T04:43:13.040 に答える
0

gems のメモリ リークの問題を解決できない場合に備えて:

回答https://stackoverflow.com/a/1076445/3675705で説明されているように、フォーク内で sidekiq ジョブを実行できます。

アプリケーションヘルパー「do_in_child」を追加してから、ワーカー内に追加するだけです

 def perform
   do_in_child do
     # some polluted task
   end
 end

はい、Sidekiq はスレッドで動作する必要があるため、これは一種の汚いソリューションであることはわかっていますが、私の場合、nokogiri による大きな XML ファイルの解析で遅いジョブがあるため、本番用の唯一の高速ソリューションです。

「高速」スレッド機能は何の利点もありませんが、メモリ リークにより、10 分間の作業後に 2GB 以上のメイン sidekiq プロセスが発生します。そして、1 日後に sidekiq 仮想メモリが 11GB (サーバーで利用可能なすべての仮想メモリ) に増加し、すべてのタスクが非常に遅くなります。

于 2015-03-04T06:17:27.137 に答える