PHP で非同期通信
PHPでWebサーバー側で処理をするとき、更新に時間がかかる処理だと、POSTしてからページが表示されるまでのタイムラグが気になります。
ページ表示に直接関係のない処理であれば、バックグラウンドで実行させることができれば、よりスムーズなブラウジングができるので、以前からいろいろと方法を考えていました。
PukiWikiMod では、PHPが自身でもう一度Webサーバーにリクエストするという方法をとっていますが、これは、いまいち美しくないし、かっこ悪いです。
そもそも、ローカルからのアクセスを禁止している場合もあるので、何とかしたいと思っていました。
そこで、今開発中の xpWiki では、ブラウザとの接続を一旦切って、もう一度リダイレクトさせたあとも、PHP側では実行を続けるという方法を考えてみました。
実際のスクリプトコードは、次のような感じです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| $_udp_file = $const['CACHE_DIR'].$this->encode($vars['page']).".udp";
if (file_exists($_udp_file)) {
$_udp_mode = join('',file($_udp_file));
unlink($_udp_file);
// ブラウザとのコネクションが切れても実行し続ける
ignore_user_abort(TRUE);
// ブラウザにはリダイレクトを通知
$base = preg_replace("#^(https?://[^/]+).*$#i","$1",$const['ROOT_URL']);
$uri = $base.$_SERVER['REQUEST_URI'];
while( ob_get_level() ) { ob_end_clean() ; }
$out = "\r\n";
header("Content-Length: ".strlen($out));
header("Connection: close");
header("Location: " . $uri);
echo $out;
flush();
// ブラウザは再表示し、PHPは実行を継続
sleep(5);
$this->plain_db_write($vars['page'], $_udp_mode);
exit();
}
|
これは、 xpWiki の実際のコードで、時間の掛かる検索用テキストデータベースの更新を、バックグラウンドで行わせています。
終了時のイベントが新しいプロセスでリアルタイムに拾えるわけではないので、非同期通信もどきですが、結構使えるのではないかと思っています。
