トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS

PHP/非同期処理(マルチスレッド処理、バックグラウンド処理)

Last-modified: 2010-05-14 (金) 14:23:28 (2685d)
Top / PHP / 非同期処理(マルチスレッド処理、バックグラウンド処理)

PHP

某案件で処理時間の長いWebAPIが1つ有り、それをすぐに返す必要があったため「起動WebAPI」と「結果取得WebAPI」に分けることとなりました。 「起動WebAPI」ではとりあえず受付完了の結果をすぐに返すと共に、裏で非同期処理(マルチスレッド処理、バックグラウンド処理)を動かす必要が出ました。 そこで非同期処理を実現する方法を考察しました。

curlを用いた非同期処理

curlを用いて複数のWebAPIを同時に呼び出し、すべての処理が終わってから処理を続ける方法が書かれています。
WebAPI1つずつ呼び出すのに比べて処理時間が短くなります。
またcurl以外に次の方法も有りますが、PHPをCGIモードで動かしているときしか使えないので使えないそうです。(== 多くの場合で利用されるApacheモジュールとして動かしていると使えない)

  • pcntl_forkというプロセスをフォーク(複製)することができる関数を利用する方法
  • 「system('php -f test.php > /dev/null &'); 」といったふうに起動する方法
    『もちろん長時間動かす時はset_time_limitの設定も忘れずに。ignore_user_abortを使えばバックグラウンド処理も可能です。』だそうです。
    これらの設定は他の方法でも入れるほうがいいようです。
    便利そうですが、PHP拡張モジュールであるcurlがウェブ側設定によって使えない場合は利用できませんので、 今回案件では使用しませんでした。

HTTPリダイレクトを用いた非同期処理

HTTPリダイレクトを用いてブラウザへのレスポンスはリダイレクト先で直ぐに返し、バックグラウンド処理はリダイレクト元で続ける方法です。 試してみました。ブラウザからリダイレクト元を呼び出すとHTTPリダイレクト先がすぐに表示されました。
今回案件ではPHPプログラムでリダイレクト元を呼んだときに、リダイレクト先で作られたXMLデータを返して欲しかったのですが、HTTPレスポンスコード500 Internal Server Errorとなってしまいました。おそらくPHPからの呼び側でHTTPリダイレクトに対応していないためと思われます。

ソケットで非同期処理を起動

呼び出し元はすぐに返り、バックグラウンドをソケットで起動する方法です。こちらが動作OKでしたので採用しました。

引用


35 名前: 電動ナナシ  投稿日: 01/10/23 03:18 ID:We7XcUx8
    >>32
    まあ要するにスクリプトを非同期で実行したいってことかな。

    これでどうかな。async_caller.php から async_called.php を呼ぶコード。
    async_caller.php が先に終了するが、called は caller が終了してもバック
    グラウンドで実行される。caller に表示されるタイムスタンプが called が
    test.dat に記録するタイムスタンプより前であることから確認できるだろう。
    Windows2000 + Apache 1.3.20 + PHP 4.0.6 で確認。

    async_caller.php
    <?php
    $fp = fsockopen ("localhost", 80, $errno, $errstr, 5);
    if (!$fp) {
        echo "Error: $errstr ($errno)<br>\n";
    } else {
        socket_set_blocking($fp, false);
        fputs ($fp, "GET /hoge/async_called.php HTTP/1.0\r\n\r\n");
        fclose ($fp);
        echo "Current time: " . time() . "<br>\r";
    }
    ?>

    async_called.php
    <?php
    ignore_user_abort();
    sleep(10);
    $fp = fopen("test.dat", "w");
    fputs($fp, time());
    fclose($fp);
    ?>

sysem関数でwgetを使用する方法

unix系でwgetコマンドが使えると次のように記述できるそうです。

$url = "http://localhost/?m=sleep";
system('wget -t 1 {$url} > /dev/null & ');

関連リンク