7

定期的に(1時間ごとに)スクリプトを実行するスケジュールされたタスクがあります。このスクリプトは、データベースおよびファイルシステムとのやり取りが多く、実行に数分かかります。問題は、スクリプトの実行中にサーバーのCPU使用率が急上昇し、通常の操作が遅くなることです。このプロセスを抑制して、時間がかかりますが、多くのリソースを消費しないようにする方法はありますか?

PHPのさまざまな構成オプションを調べましたが、自分のニーズに合うものはないようです。

php.iniのmemory_limitを低い値に設定すると、データオブジェクトが非常に簡単にオーバーフローします。

スクリプトの特定のポイントでsleep()を使用することを提案した同様の投稿を見ましたが、それでもスクリプトがサーバーをスパイクするのを防ぐことはできません。

最適な解決策は、ランプ(この場合はWamp)スタックに最大CPU使用率10%のみを使用するように指示する方法です。私はランタイムについてはまったく心配していません。1秒あたりのCPUサイクルを節約することを意味する場合は、もっと時間がかかることを望んでいます。私の代替ソリューションは、データベースレプリケーションを使用して別のサーバーをセットアップし、cronが他のすべての速度を低下させることなく町に行くことができるようにすることです。

環境:Windows Server 2k3、Apache 2.2.11、PHP 5.2.9、MySQL 5.1

この状況についての洞察に感謝します。

編集: * nix固有の回答も含め、すべての回答に感謝します。私の状況では、ホスティング環境を変更するのはまだ十分早いです。うまくいけば、この質問はOSに関係なく他の人を助けるでしょう。

4

9 に答える 9

8

これは難しい問題です。コマンドラインからPHPスクリプトを実行している場合は、プロセスのスケジューリングの優先度を低く設定できます(start /low php.exe myscript.php私は信じています)。PHPスクリプト自体が、CPUを消費している処理のほとんどを実際に実行している場合、これは機能する可能性があります。ただし、データベースとファイルシステムの相互作用が重いとのことでしたが、このソリューションでは役に立ちません。INSERTクエリとUPDATEクエリに役立つMySQLヒント「LOW_PRIORITY」があるようですが、私はそれらを試していません。

于 2009-04-15T16:02:39.307 に答える
3

UNIX(LAMP)では、ループを続行する前にサーバーの負荷をチェックすることで問題を解決できました。

function get_server_load($windows = 0) {
    $os = strtolower(PHP_OS);
    if(strpos($os, "win") === false) {
        if(file_exists("/proc/loadavg")) {
         $load = file_get_contents("/proc/loadavg");
         $load = explode(' ', $load);
         return $load;
        }
        elseif(function_exists("shell_exec")) {
         $load = explode(' ', `uptime`);
         return $load;
        }
        else {
         return "";
        }
    }
}

for(... ... ...){
    $data = get_server_load(); 
    if($data[0] < 0.2){
     // continue
    }else{
        sleep(1);
    }
}

この機能はWindowsでも動作するはずですが、保証はできません。Linuxでは、最後の1分、5分、15分の負荷でアレイが返されます

また、スクリプト(CLIの場合)を低い優先度で開始することを検討してください(Linuxでは「nice」を使用してください)

Apacheのアクティブなプロセスの数(httpd.confでmod_statusを有効にした場合はページ127.0.0.1 / server_status?autoを解析できます)やMySQLの状況(アクティブな接続)など、ループを続行する前に他の値を使用することもできます。 ?)

于 2009-04-16T01:27:11.977 に答える
3

Windowsのプロセスの優先度を低く設定できます。プロセスがどのように開始されるかはわかりませんが、プロセスを低優先度に設定した場合、優先度を実際に低く設定すると、CPUリソースが必要なものはすべてそれらを取得します。

于 2009-04-15T16:00:23.417 に答える
2

クライアントにサービスを提供し、データを分析するためにサーバーを使用することはお勧めできません。

したがって、最終的な解決策を探している場合は、アプリケーションをいくつか再設計し、データ分析をフロントエンドとライブデータベースからこのタスク専用の別のシステムにオフロードします。

アナライザーを正常に調整できたとしても、貴重なリソースを使い果たしてしまいます。そうしないと、ユーザーにサービスを提供するために利用できるようになります。

于 2009-04-15T16:09:51.490 に答える
2

niceを使用してスクリプトを起動するようにcronエントリを変更できますか?

于 2009-04-15T16:07:49.827 に答える
1

これは難しい変更かもしれませんが、データ構造をイテレーターにリファクタリングする価値があるかもしれません。また、コードに循環参照がある場合は、これらのオブジェクトの設定を解除するclearReferences()のようなメソッドを提供します。ちなみにこれはPHP5.3で解決された問題です。

だからあなたが持っているなら:

class Row
{
    protected $_table;

    public function __construct($table)
    {
        $this->_table = $table;
    }
}

class Table
{
    protected $_row;

    public function __construct()
    {
        $this->_row = new Row($this);
    }
}

clearReferences()メソッドをRowクラスに追加します。

class Row
{
    public function clearReferences()
    {
        $this->_table = null;
    }
}

今のところ思いつくのはそれだけです。

于 2009-04-15T15:59:39.097 に答える
1

niceを使用して同様の方法でcronから実行するスクリプトがたくさんあります。

0 * * * * nice -n19 php myscript.php

これはRAMの使用率には役立ちませんが(スクリプトの記述方法を変更するだけでそれが可能になります)、それ以外の場合はアイドル状態になるCPUのみを使用します。

編集:質問がWindows環境に関係していることを確認しませんでした、申し訳ありません...同じ問題を抱えている*nixユーザーのためにこれを残します。

于 2009-04-15T16:20:59.297 に答える
1

おそらく、スクリプトが一度にやりすぎを試みているだけなのかもしれません。1時間に3回実行した場合、それは少なくなりますか?

別の解決策は、この種の「バックエンド」処理を実行するためだけに追加のサーバーをセットアップすることです。これは、Webサーバーだけでなく、データベースに過度の負荷をかけない場合に特に効果的です。

見るべきさらに別のアプローチは、それが仕事を別の方向に分割できるかどうかです。これらの種類のスクリプトには、多くの場合、多数の小さなSQLステートメントを生成するために使用される結果を生成するいくつかの大きなSQLステートメントが含まれています。後者をどこかに置いておくことができれば、後のステップとしてデータベースに対して実行できます。このようなアプローチでは、バッファリングされていないクエリを使用して前処理データをフェッチできる場合もあります。これにより、PHPコードによるメモリ消費量を大幅に削減できます。

于 2009-04-17T04:55:51.903 に答える
0

it(Apache)をサービスとして実行している場合は、Winコントロールセンター/サービスで優先度設定を変更できます。とにかくCPU使用率は急上昇しますが、スケジューラーは他のプログラムを優先します。また、データベース/サーバーをアプリケーションとは別のHDに配置してみてください。

于 2009-04-15T16:00:56.863 に答える