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

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

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

[[PHP]]



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



*curlを用いた非同期処理
-[[[EC studio技術ブログ]PHPでマルチスレッド(バックグラウンド処理、非同期処理)を実現する方法>http://techblog.ecstudio.jp/tech-tips/php-multi.html]]

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リダイレクトを用いた非同期処理
-[[[nao pon's Blog]PHPで非同期通信>http://xoops.hypweb.net/modules/UsersWiki/person/nao-pon/blog/2006-11-17]]

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



*ソケットで非同期処理を起動
-[[2ch 【PHP】質問スレッドPart2>http://ebi.2ch.net/php/kako/1003/10032/1003283567.html]]

呼び出し元はすぐに返り、バックグラウンドをソケットで起動する方法です。こちらが動作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を使用する方法
-[[PHPでfork(バックグランド処理)をする方法>http://d.hatena.ne.jp/haru-komugi/20090128/1233111963]]

unix系でwgetコマンドが使えると次のように記述できるそうです。
 $url = "http://localhost/?m=sleep";
 system('wget -t 1 {$url} > /dev/null & ');



*関連リンク
-[[とても簡単にPHPからPOSTリクエストを送信する方法【PHP】>http://www.programming-magic.com/20080226023511/]] 色々なPOST通信方法が書かれています。
-[[[作業日報]ignore_user_abort(false)でPHPが処理を中断しない件>http://blog.jojo.jp/?eid=867079]]
-[[[個人的な備忘録]PHP の ob_implicit_flush()>http://www.asahi-net.or.jp/~wv7y-kmr/note/2004-01.html#YMD20040125_PHP]]
-[[PEAR HTTP_requestマニュアル>http://pear.php.net/manual/ja/package.http.http-request.php]]
-[[[オーガニック・ウェルス]PHPでfsockopenの自分サンプル>http://ict-start.com/blog/?p=27]] 例外処理が参考になります。
-[[PHPのcURLモジュール マニュアル>http://websys-memo.biz/php_manual_ja/ref.curl.html]]
-[[PHP API仕様書 fsockopen>http://php.net/manual/ja/function.fsockopen.php]]
-[[[phpspot]ソケットの使いかた>http://phpspot.net/php/pg%83%5C%83P%83b%83g%82%CC%8Eg%82%A2%82%A9%82%BD.html]] fsockopenで外部サイトをGETするシンプルなサンプル
-[[[オデの日記]fsockopen()でタイムアウト>http://koexuka.blogspot.com/2009/02/webad-phpfsockopen-php-resource.html]] タイムアウトについての考察。soket_set_timeout()とstream_get_meta_data()を使え!
-[[HTTPクライアント - fsockopen() fputs() fgets() fclose() parse_url() urlencode()>http://www.spencernetwork.org/memo/tips-3.php]] fsockopenサンプル
-[[[phpspot]PHP用、外部接続にcURLかfsockopenが選べるHTTPクラス>http://phpspot.org/blog/archives/2008/01/phpcurlfsockope.html]]
-[[[MEMORVA]Socket(ソケット)でデータを送信・受信>http://memorva.jp/memo/php/fsockopen.php]] HTTP/1.1とHTTP/1.0の違い説明などが分かりやすいです。
-[[[しゃもしゃも日記]ファイル添付でHTTP POST(PHP)>http://d.hatena.ne.jp/shamoshamo/20080502]] ファイル添付に対応したfsockopenサンプル
-[[[レッツPHP!]Webページの処理他>http://php.s3.to/tt/tt6.php]] 各種HTTP関連関数の解説
-[[[PHP基礎]POST通信を行う>http://capsulecorp.studio-web.net/tora/php/serverside2/Ex016post.html]] fsockopen POST通信サンプル。目的別の色々なサンプルが有ります。
-[[[Narutyonet]PHPでPOSTさせる方法(fsockopen編)>http://narutyo.net/?no=12]] fsockopen POST通信サンプル