2015-11-23 49 views
9

私はApacheサーバー、PHPアプリケーションに大きな問題があります。PHP readfile()は終了せず、Apacheサーバーをハングアップさせます

サーバーは、PHPで動作している非常に高いトラフィックのWebサイトを提供しています。

24時間または48時間ごとに、apacheがハングアップし、ウェブサイトに再びアクセスできるように再起動する必要があります。私はそれをリブートしなければなりません。なぜなら、apacheは許可されたプロセス/サーバ(私にとっては16000)の最大数に達し、他のプロセスはすべてアクティブなので、他のプロセスを解放することはできません。

このサーバーでホストされているWebサイトは、最後にファイルを提供するPHPアプリケーションです。ダウンロードサーバーといいます。

ファイルは、POSTリクエストを送信するフォームを介してブラウザから要求されます。

問題は、この投稿要求は決して終わらないようです(私のサーバーステータスのほぼすべての16000プロセスがPOSTリクエストであることがわかります)。 (私はhrefのリンクとそれらを提供したくない、そうなるように、私は、フォームのPOSTリクエストを使用して提供しています

ファイルは大きなファイル(2Gまで10M)であり、私はPHPののReadFile関数とそれらを提供しますファイルシステム上のどこにファイルが存在するかわかりません)。

phpのreadfileを使用する関数は、最後にexit()を使用しても決して終了しないようです(下記のコードスニペットを参照)。

私は私のPHPコードによって引き起こされ、この終わることのないPOSTリクエストを回避する方法についてはこちらを求めています。私は、POSTファイルの提供方法を​​維持したい。

まず私のconf:128G RAM :MPMのpreforkの

  • PHP 5.5.9(MOD PHP)
  • ハードウェアと

    • Ubuntuのサーバ14.04
    • のApache 2.4

      私mpm_prefork.confファイル:

      <IfModule mpm_prefork_module> 
           StartServers    512 
           MinSpareServers   512 
           MaxSpareServers   1024 
           ServerLimit    16000 # no problem with my server ram 
           MaxRequestWorkers  16000 
           MaxConnectionsPerChild 10000 
      </IfModule> 
      

      私apache2.confファイル:

      ... 
      Timeout 300 
      KeepAlive On 
      MaxKeepAliveRequests 500 
      KeepAliveTimeout 5 
      ... 
      

      私のPHP。iniファイル:

      max_execution_time = 7200 
      

      私のApacheのログファイル:私の問題のための興味深い

      問題が発生したときに表示さのmuninのグラフ: enter image description here

      私のApacheサーバのステータスそのような外見で: enter image description here

      enter image description here

      そして、私のサーバ・クラス(問題を引き起こしているコード):

      class Server 
      { 
          /* the file is served from a remote url source */ 
          public function serveFileFromUrl() 
          { 
           if (empty($_POST)) { 
            return; 
           } 
      
           $url = $_POST['file_url']; 
           $mime = $_POST['mime']; 
           $name = sanitizeFileName($_POST['name']) . uniqid() . '.' . $mime; 
           $size = $_POST['size']; 
      
           if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) { 
      
            // for Internet Explorer 
            if ($mime == 'mp3') { 
             header('Content-Type: "audio/' . $mime . '"'); 
            } else { 
             header('Content-Type: "video/' . $mime . '"'); 
            } 
            header('Content-disposition: attachment; filename="' . $name . '"'); 
            header('Expires: 0'); 
            if ($size !== '') { 
             header('Content-Length: ' . $size); 
            } 
            header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
            header("Content-Transfer-Encoding: binary"); 
            header('Pragma: public'); 
      
           } else { 
      
            // not for internet Explorer 
            if ($mime == 'mp3') { 
             header('Content-Type: "audio/' . $mime . '"'); 
            } else { 
             header('Content-Type: "video/' . $mime . '"'); 
            } 
            header('Content-disposition: attachment; filename="' . $name . '"'); 
            header('Expires: 0'); 
            if ($size !== '') { 
             header('Content-Length: ' . $size); 
            } 
            header("Content-Transfer-Encoding: Binary"); 
            header('Pragma: no-cache'); 
      
           } 
      
           ob_end_clean(); // fix memory problems with readfile (http://heap.tumblr.com/post/119127049/a-note-about-phps-output-buffer-and-readfile) 
           flush();  // fix memory problems with readfile 
           readfile($url); 
           @ob_end_flush(); 
           exit(); 
          } 
      
          /* file is served from my filesystem */ 
          public function serveFileFromPath() 
          { 
           if (empty($_POST)) { 
            return; 
           } 
      
           $url = APP_PATH . '/download/' . $_POST['file_name']; 
           $mime = $_POST['mime']; 
           $name = sanitizeFileName($_POST['name']) . '-' . uniqid() . '.' . $mime; 
           $size = $_POST['size']; 
      
           if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) { 
      
            // for Internet Explorer 
            if ($mime == 'mp3') { 
             header('Content-Type: "audio/' . $mime . '"'); 
            } else { 
             header('Content-Type: "video/' . $mime . '"'); 
            } 
            header('Content-disposition: attachment; filename="' . $name . '"'); 
            header('Expires: 0'); 
            if ($size !== '') { 
             header('Content-Length: ' . $size); 
            } 
            header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
            header("Content-Transfer-Encoding: binary"); 
            header('Pragma: public'); 
      
           } else { 
      
            // not for internet Explorer 
            if ($mime == 'mp3') { 
             header('Content-Type: "audio/' . $mime . '"'); 
            } else { 
             header('Content-Type: "video/' . $mime . '"'); 
            } 
            header('Content-disposition: attachment; filename="' . $name . '"'); 
            header('Expires: 0'); 
            if ($size !== '') { 
             header('Content-Length: ' . $size); 
            } 
            header("Content-Transfer-Encoding: Binary"); 
            header('Pragma: no-cache'); 
      
           } 
      
           ob_end_clean(); // fix memory problems with readfile (http://heap.tumblr.com/post/119127049/a-note-about-phps-output-buffer-and-readfile) 
           flush();  // fix memory problems with readfile 
           readfile($url); 
           @ob_end_flush(); 
           exit(); 
          } 
      } 
      

      誰かが終わることはありませんPOSTリクエストを回避するためのソリューションを持っていますか? 問題を解決できるかどうかは、PHP以外の方法でファイルを提供するのは大丈夫です。

      してくださいなし複製、私はこの質問を特定するために十分なコード、confにスニペットや写真を追加した:)

  • +2

    そのコードの50%を取り除くための簡単な方法は、ヘッダロケーション別名、HTTPリダイレクトとserveFileFromUrl()部分を交換することであろう。それはあなたの問題をどんな運にも修正するかもしれません。 – Calimero

    +1

    タイムラインを0に設定しました。 tisは確かに修正ではありませんが、10時間のようなものを設定すると、今のような何かが失敗してもサーバーが生き残ります。スクリプトを実行すると考える時間を2倍に設定します。 – Elentriel

    +0

    @Calimeroもし私がヘッダの場所だけを使うならば、ファイル(これはビデオファイルです)がブラウザで再生されます。ファイルをダウンロードします。 – hedi

    答えて

    3

    mod_xsendfileは、ファイルを提供するPHPの良い代替手段です。それは永遠に実行することはできませんので、あなたは、単に、あなたのPHPスクリプトにいるtimelimitを追加することができそうで

    https://tn123.org/mod_xsendfile/

    http://php.net/manual/de/function.set-time-limit.php

    +0

    max_execution_timeはすでに2時間に設定されていますphp.iniファイル。私はそれで質問を更新しました。 – hedi

    +0

    あなたのユースケースでは、mod_xsendfileを本当に考慮する必要があります。それについての別の記事:http://codeutopia.net/blog/2009/03/06/sending-files-better-apache-mod_xsendfile-and-php/ – user5542121

    +0

    おかげさまで、お世話になります。私は2週間前にそれを試してみましたが失敗しました:それは0kbのファイルを提供していました。 – hedi

    関連する問題