0

いくつかの「重労働」タスク(30秒から3分)を処理する必要があるWebアプリ(php)を実行しています。それほど重くないことはわかっていますが、ユーザーを待たせることができないため、次のような内部APIを設定しましたhttp://localhost/process-picture/745884/。この操作をMySQLテーブルに保存します。

次に、そのMySQLテーブルをフェッチし、最も古いキューに入れられた操作を実行する「プロセス」を作成します。これが完了すると、次の操作を取得します。

まず、cURLで次のようなシステムを呼び出すPHPスクリプトを作成することを考えました。

fetchOperation.phpDBに接続し、操作へのURLを取得してcURLで呼び出します。すべての操作:それ自体を実行し、その後、キューから自分自身を削除して、(cURL)fetchOperation.phpを再度呼び出します。

このシステムはちょっとトリッキーだと思うので、15秒ごとにDBをチェックして次のことを行うバックグラウンドプロセスを設定する方法があるかどうか(そしてどの言語でシステムを作成するか)疑問に思いました。

  • としてマークされたすべての行を削除しますDONE
  • とマークされた行があるかどうかを確認します。ある場合はPROCESSING、終了して次の15秒待ちます。
  • 行がない場合PROCESSINGは、最も古い行PENDING(FIFOキュー)を起動します。

このようにして、いつでも処理されているものを管理でき、サーバーの負荷を制御することもできます(たとえば、夜間は最大3つのPROCESSINGアイテムを使用できます)。

長い説明をしてすみません、そしてよろしくお願いします!

4

2 に答える 2

4

cronでジョブをスケジュールする必要があるようです。cron はスクリプト/プログラムを実行するだけなので、その実装はスケジューリング自体とは異なります。

Cronは起動/忘れるだけなので、そこから任意の期間のプロセスを呼び出すことができます(以下の実行時間のコメントを見ています-誤解していた場合は修正してください)

于 2012-09-28T09:19:33.563 に答える
0

最後に、私はそれをそのように解決しました:

1位。URL 呼び出しが可能なように操作を設計します。例えば:http://localhost/render-image/14523665

2番目。保留中の操作を次のようなテーブルに保存します: operations(operation-id, operation-url, operation-status)。

これが準備できたら、次のことを行う短い PHP スクリプトを設計しました。

<?php
if( WORKER_IS_ONLINE !== true ) exit();
OperationsQueue::CleanQueue();
while( OperationsQueue::RunningOperations() < WORKER_MAX_OPERATIONS ) {
    launch_operation( OperationsQueue::DequeOperation() );
}
sleep( WORKER_SLEEP_TIME );
launch_operation( '/operations_queue/deque' );

この補助関数 (launch_operationおよびOperationsQueueクラス) は次のように動作します (まだ実装されていないことに注意してください)。

<?php 
define('WORKER_SLEEP_TIME', 15);     // Time to sleep between sweeps.
define('WORKER_HOST', 'localhost');  // Hostname where the operations will be performed.
define('WORKER_PORT', 80);       // Port where the operations will be performed.
define('WORKER_SOCKET_TIMEOUT', 80); // Port where the operations will be performed.
define('WORKER_MAX_OPERATIONS', 2);  // Max simultaneous operations.
define('WORKER_MAX_LAUNCHES', 2);    // Max operations launched within a sweep.
define('WORKER_IS_ONLINE', false);   // Bool value that marks whether the worker must be working or not.

function launch_operation($operation) {
    $fp = fsockopen(WORKER_HOST, WORKER_PORT, $errno, $errstr, WORKER_SOCKET_TIMEOUT);
    if ($fp) {
        $out  = 'GET ' . $operation . " HTTP/1.1\r\n";
        $out .= 'Host: ' . WORKER_HOST . "\r\n\r\n";
        fwrite($fp, $out);
        fclose($fp);
    }
}

class OperationsQueue {

    public static function RunningOperations(){
        // connect to DB an perform: SELECT COUNT(*) FROM operations WHERE status = 'PROCESSING';
        return 1;
    }
    public static function CleanQueue(){
        // connect to DB an perform: DELETE FROM operations WHERE status IN ('DONE', 'CANCELED');
    }
    public static function DequeOperation(){
        // connect to DB an perform: SELECT * FROM operations WHERE status = 'PENDING' ORDER BY id ASC LIMIT 0, 1;
        // UPDATE operations SET status = 'PROCESSING', tries = tries+1 WHERE id = $id;
        return 'operation_url';
    }

}

他の人にも役立つと思いました。ご覧のとおり、操作が連鎖しています。

于 2012-09-28T14:45:18.173 に答える