Help us understand the problem. What is going on with this article?

メモリを使いすぎたPHPから無理やり解放させる

More than 3 years have passed since last update.

環境:CentOS7 + apache2.4(prefork) + PHP5.4

現象

  • PHPの処理が終了してもメモリの使用量が回復しない画面(処理)がある。
  • MaxRequestsPerChildに達するとapacheのプロセスが終了してメモリ使用量も回復するが、特定の画面だけでその現象が発生しているため、時にはMaxRequestsPerChildに達する前にサーバーのメモリを使い切ることがある。
  • というか、複数プロセスあるんだから、普通はそうだよね。
  • ぶっちゃけメモリリークなんだろうけど、発生個所が曖昧なのと、特定環境でのみしか発生しないため、調査が難航。

理想

  • PHP処理が終了したら、PHPが使ったメモリを解放する。

現実

  • unsetや循環参照の怪しそうなところを潰してみたけれど、環境によって発生コードが異なっていて、そもそもの根本原因がわからない状態なので、どこまで対応すれば完了と言えるのかの根拠がない(運用に乗せられない)。

迷走

  • MaxRequestsPerChildを1にする
    ⇒メモリを大して使わないPHPや、js、css等へのリクエストにも毎回子プロセスを生成するのはパフォーマンスが心配
  • 定期的にapacheの再起動を行う
    ⇒定期的って具体的にいつよ?(少なくとも1日1回夜間に再起動のペースでは間に合わない)

その他、MaxRequestsPerChild=1用のapacheと通常のapacheを用意するとか考えはしましたが、変更点が多くなり影響範囲が広がりすぎるので断念。

採択

  • メモリをたくさん使う(ことのある)画面については特定できているので、メモリをたくさん使った場合はMaxRequestsPerChildの値に関係なく、そこでプロセスを終了として、apacheが確保したメモリを解放させる。
  • 分かりやすく言うと、太ったPHPに自殺させます。

強制解放

http://php.net/manual/ja/function.apache-child-terminate.php
apache_child_terminate()

ただし、

もし PHP が Apache 1 モジュールとして実行している場合、TRUE を返します。

これが原因なのか、メモリは回復せず。

真・強制解放

function mightRelease(){
    //メモリ解放閾値:この値以上にメモリが使われていた場合はプロセスを落とす
    $memory_byte_threshold = 1024 * 1024 * 200;

    $memory_byte_usage = memory_get_peak_usage(true);
    if($memory_byte_usage > $memory_byte_threshold){
        //処理終了時に実行する関数を登録
        register_shutdown_function(function(){
            posix_kill(getmypid(), 28);
        });
    }
}

この関数をpostExecute的なところで呼び出す。
200MB以上使った画面だけ、プロセスが終了し、メモリが解放されていることを確認。
終了した直後は子プロセス数は減るが、数秒後にはちゃんと規定数まで増えていることも確認。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした