Typo 5.3がメモリを使い過ぎる

投稿者 akira 2009-06-28 09:28:00 GMT

二、三日前から時々oom-killerが出るようになった。なんでかなと見てみたらずいぶんと太ったTypoのプロセスサイズがいくつか。一つあたり500MBとか……。

今までなんともなかったのになと思ったものの、それほど考えてみれば気にしていなかっただけで、実はけっこう前からこういう状態だったのかもしれないということに気付いた。おおむね自分が困るだけとはいえ、ちょっとほったらかしすぎた。動きを見てみると、プロセスが生成されて少しして数秒かけてプロセスサイズが大きくなっていくことがわかった。どうやら何かを読み込んでいるように見える。

実はこのことに気付くほんの少し前のタイミングでPassengerのバージョンを変えたり、他のアプリケーションの配置を変えたり、GEM_HOMEを変えたりということをしている。そのため、まず疑ってしまったのはそのあたりだった。その次に疑ったのは自家製コードのいくつか。といってもTypoのためには数十行のコードを書いた程度で、特別に問題になりそうなものは見付からない。

動いているプロセスにコードをつっこんでオブジェクトの様子を見てみるかとも思い始めていたのだが、ここでscript/consoleでも同じ現象が出ていることに気付いた(遅い!)。そしてconfig/environment.rbを読み込み終えるまでにプロセスサイズが育っていることがわかった。printfデバッグで絞り込みをかけたところ、以下のコードにいたった。

if RAILS_ENV != 'test'
  begin
    ActiveRecord::Base.connection.select_all("select * from sessions")
  rescue
    begin
      ActiveRecord::Base.connection.current_database
      Migrator.migrate
    rescue
      # if there are no database, migrator doesn't no start
      # use case : rake db:create in rails tasks
    end
  end
end

このコードが加えられたのはこのあたり。これなら、とりあえずはlimit 1でも付けておけばよいだろうか。もっとやりようがありそうなものではあるが。

結局、問題が顕在化したのは保存しているセッションの数が多くなってきたからであった。実に602,788レコードもある。セッションデータの掃除は今でも(Typo 5.3ではRails 2.2を使っているが)手作業でやるのかな? (セッションだからdelete_allで十分かしら?)

$ script/runner -e production 'CGI::Session::ActiveRecordStore::Session.destroy_all(["updated_at 

追記

問題として報告しておいたところgithub上のリポジトリでは引用したブロックはコメントアウトされたようだ。5.3.1では直っているのかな。なんだか他のチケットも動き出したので、ちょうどそんなタイミングだったらしい。

Flickr APIの変化とTypo 5.3のflickr.rb

投稿者 akira 2009-05-30 13:17:00 GMT

Typo 5.3で使っている自作のFlickrプラグインで写真を引っぱれなくなった。「Flie does not exist」という例外が起きている。ファイル?

追ってみたところ、vendor/flickr/flickr.rbで使っているXmlSimple.xml_inの中での起きている例外だった。xml_inは与えられた文字列がXMLっぽかったらXMLとして、そうでなければファイル名として処理しようとする。えぇー、と思ったが、まあそれはおいていおく。

実際にアクセスしているURLを取り出してwgetしてみたところ、きちんとレスポンスが得られる。けれどもxml_inには空文字列が渡っている。おかしいなと思い、flickr.rbではどのようにアクセスしているか見てみるとNet::HTTP.get_responseを使っていた。それではと同メソッドでアクセスしてみると302が返ってきていることがわかった。なるほど。

では302が返ってきたらそれを追いかけるように書き換えて、などとしかけたのだが、open-uriでよいではないかと思いとどまった。こんな感じ。

def http_get(url)
#  Net::HTTP.get_response(URI.parse(url)).body.to_s # 元のコード
  open(URI.parse(url)) {|i| i.read}
end

Typoインストールメモ

投稿者 akira 2008-11-10 08:40:00 GMT

まずTypoのコードを入手する。いろいろなも味に依存しているのでRubyGemsを使うのが楽。

$ GEM_HOME=/tmp/GEM gem install typo

Typoではサイトをセットアップするときに必要なものをすべてコピーするので、インストールしたgem群への依存関係は一応なくなる。ただし、typoコマンドを通じてバックアップなどの管理操作ができる。そしてそのような操作のためにはインストールされたgemが必要となる)。

$ sudo -u www-data \
  env GEM_HOME=/tmp/GEM \
    /tmp/GEM/bin/typo install path/to/install/dir \
     db_user=dbuser \
     db_password=dbpass \
     db_name=dbname \
     web-server=external # FastCGIの場合

これでTypoが動作する環境ができるが、.htaccessは作ってくれないのでこれを作っておく(FastCGIで動かそうと思うので)。また、Rails 2.x系ではw3mなどでアクセスすると406エラーになるので回避コードを入れておく。

$ rails /tmp/t
$ sudo -u www-data \
  cp /tmp/t/public/.htaccess path/to/install/dir/public
$ rm -rf /tmp/t
$ sudo -u www-data \
  vi path/to/install/dir/putlic/.htaccess # 調整
$ cat <path/to/install/dir/config/initializers/w3m.rb
Mime::HTML.instance_eval { @synonyms << "text/*" }
Mime::LOOKUP["text/*"] = Mime::HTML
E

今回、tDiaryから移行したデータがあるので、一部の表現のために書いた互換プラグインを置いておく。

$ sudo -u www-data \
  cp -a typo_textfilter_{asin,tdiarycompat} \
    path/to/install/dir/vendor/plugin

最後にApache HTTPサーバ側のその他の調整をしてリロードする。

$ sudo vi /etc/apache2/sites-available/site # その他調整
$ sudo /etc/init.d/apache2 reload

ブラウザでアクセスすると最初のユーザ登録ができる。tDiaryからのデータ移行の都合のためspamまわりの設定を残して、その他の設定をしておく。その後でデータを流し込む。

$ sudo -u www-data \
 path/to/install/dir/script/runner td2typo.rb tdiary.dump

終了後、残しておいたspamまわりの設定をし、動作確認をする。

この環境ではFastCGIをmod_fcgidで運用しているのだけど、外部リソースにアクセスしまくるページなどでIPCCommTimeoutにひっかかることがあるようだった。tDiaryをFastCGIで動かそうとしたときにはIPCConnectTimeoutを大きめにしなければならなかったのだけど、ここではCommのほうを大きめに設定した。

実はnet/httpのタイムアウトのところでエラーになっていたのを勘違いしてしって、ずいぶん遠まわりをしてからこのことに気付いた。いかんいかん。