2011-07-31

Plone & Zope / メモリ関連のメモ

PloneをZEO化して少し幸せになったのもつかの間…。

プロセス起動直後は問題ないとして、時間がたつとプロセスが利用するメモリがどんどん増えていきます。よくよく考えると、このような状態の模様。

  • Ploneの使うZODBはトランザクションログも同じファイルに書き出すため、放っておくとどんどん大きくなる。
  • ZODBが大きくなると、その分プロセスに使われるメモリも増えてくる。(実メモリで、ZODBのファイルサイズ分くらい使う)
  • ZODBはパックすればサイズは小さくなるが、プロセスは再起動しないとメモリを解放してくれないっぽい。
    本来はGCがきちんと働いてメモリが解放されるはずですが、その通りにはいかないようです。(後述)
  • キャッシュを利かせる調整をしているため、ユーザのアクションが増えるにしたがってキャッシュに使われる分だけプロセスの消費するメモリも増える。

メモリを解放するには、どうやらプロセスを再起動というのが素直な方法の模様。(まあ、APサーバとしては良くある話のようです)

ただ、DBのパックは毎日行ったほうが良い、という他には、あまり情報を見たことが無かったので、”Zope, process, restart” なキーワードで検索をしてみました。

すると、案の定 plone.org にそれらしきエントリが…(^^;

ざっと読んだ限り、冒頭の説明はこんな感じ。

* * *

Zopeを定期的に再起動させる必要はないが、サイトのサイズや動作によっては、再起動がベストプラクティスとなることも考慮すべき。

なぜなら、ZopeはPythonのプロセスとして動いているので、状況によってはホストシステムの利用可能なメモリを使い切ってしまう可能性もある。

これはPythonのバグではなく、Pythonのコードのせいというわけでもない。Pythonがreference-countingなガベージコレクションの構造を持っている点が大きい。

本来は参照されなくなった、削除されたオブジェクトはGCの対象になって、メモリの増加も抑えられるはず。しかし、状況によっては、オブジェクトが利用されているかどうかを判断できないことがある。また、相互参照しているオブジェクトが多ければ、どうやって適切な順番でオブジェクトを削除していいか判断が付かないということが起こり得る。

こうなると、オブジェクトの破棄が行われず、占有されてしまったメモリが解放できないので、プロセスを停止してPythonのメモリをいっさいがっさいクリーンアップさせるしかない。

(こういう動作を妙に思うのであれば、Pythonの__del__ method, か、gc module のドキュメントを読むべし)

結果的に、長期間稼働しているZopeのプロセスは、実際のアクティビティに必要としている以上の、非常に大きなメモリを占有してしまうことがある。そして、メモリを解放するためには、プロセスを再起動させるしかない。

* * *

…とまあ、やはりOSの状況を確認しながら、再起動は必要になってくるようです。

あとは再起動の方法、その他考慮すべきことが書かれています。

幸い、ZEOでクラスタ化したので、うまく負荷分散させながら順番にプロセスを再起動していけば、サービス停止を最小限に抑えられそうです。確かにこの点で、切り替えて良かった…と思います。

なお、ZEOクライアント(Zopeのプロセス)だけを再起動すればよく、ZEO Server(DB側) はメモリを占有することはあまりないそう。

ただし、大きく膨れてしまったZODBを pack する際には、非常に大きなメモリを必要とするらしいので、定期メンテナンスを行う時はZEO Serverのプロセスの状況も鑑みて、再起動を検討するほうがよさそう、とのこと。

この辺は、こまめにpackすれば大丈夫なのかもしれませんが、結局は良くOSの状況、パフォーマンスを監視し、自分の判断で再起動を実施するのばベストのようです…。

将来のバージョンでは、再起動も減らせるだろうと述べられていますが、Ploneのバージョン4までは、やはりPython2.4ベースなので、このエントリに従った方がよさそうです。

やっぱり、運用しないと判らないことってあるんですね。プログラムの知識とか本当に何ともし難いのですが、このへんの体験談が、何かのお役に立てれば幸いです…。

0 件のコメント:

コメントを投稿