GearmanをPHPから使ってみた。
今回は、PHPでGearmanを使えるようにして、ざっと動きを確認してみました。
Gearmanの設定はこっち
ちなみに、よく知らんのだけど、Gearmanは(GearmanClient::doのように)即時実行で結果をclientに返す用途がメジャーなのかな?
ほかのサイトだと、そういう風に紹介されてました。
GearmanCient::doBackgroundをつかうと、TheSchwartzみたい?に
ジョブを突っ込むだけ突っ込んであとはお願いね〜ということができるので
今回はこっちを使います。
はい、まず Gearman PHP Extensionを入れます。
yum install php-devel
wget http://pecl.php.net/get/gearman-0.7.0.tgz
tar xzf gearman-0.7.0.tgz
cd gearman-0.7.0
phpize
./configure
make
make install
OK。
php.iniにextensionの記述を追加します。
CentOSだと/etc/php.d/以下にiniを置けばOKぽいのでそうしてみます。
# iniファイルつくって echo 'extension=gearman.so' | cat > /etc/php.d/gearman.ini # apache再起動 service httpd restart # 動いてるかな? php -r 'print gearman_version();'
僕の環境だと、"0.14"って出力がでました。わーい
さて、さっそくテスト。
まず、worker。
ただ、printするだけ。
worker.php
<?php $worker = new GearmanWorker(); $worker->addServer(); $worker->addFunction('test', 'my_test'); while ($worker->work()); function my_test($job) { print $job->workload()."\n"; }
clientもつくる
client.php
<?php $client = new GearmanClient(); $client->addServer(); $time = time(); print $time."\n"; $client->doBackground("test", $time); if ($client->returnCode() != GEARMAN_SUCCESS) { print "faild add job!\n"; }
できた。
$ php worker.php
でworkerを起動。
別のterminalを開いて
$ php client.php
を実行するとそれぞれ
$ php worker.php
1294802686
$ php client.php
1294802686
となります。ちゃんとjobが渡ってますね。
さて、ここから障害時にどうなるかをちょっとみてみました。
workerが死んでたらどうなるの?
$ php client.php 1294802944 $ php client.php 1294802946
clientは問題なく動きます。
select * from queue; +--------------------------------------+---------------+----------+------------+ | unique_key | function_name | priority | data | +--------------------------------------+---------------+----------+------------+ | 713ed7c0-7e51-4e9a-8f99-76f66693bfd6 | test | 1 | 1294802946 | | 349f796f-6a00-4ef1-ba81-48a3b2a52468 | test | 1 | 1294802944 | +--------------------------------------+---------------+----------+------------+ 2 rows in set (0.00 sec)
mysqlにも溜まってますね。
ここで、workerを動かすと
$ php worker.php 1294802944 1294802946
jobが消化されました。
ここまでは、ジョブキューとして当然の動きですね。
gearmandが死んでたら?
$ php client.php 1294803188 PHP Warning: GearmanClient::doBackground(): gearman_connection_flush:could not connect in /home/toshiyuki/gearman_test/client.php on line 6 faild add job!
もちろん、キューに突っ込めないので、clientがエラーになります。
workerを動かすと
$ php worker.php
お、何ともなく動く。
じゃあ、ここで、gearmandを起動。
gearmand -q libdrizzle --libdrizzle-db=gearman_queue --libdrizzle-table=queue --libdrizzle-user=root -u root -d
$ php worker.php 1294803787 1294803789 1294803789 1294803790
お!来た!! これは想定外。動かないと思ったよ。
gearmand起動から、job実行まで5秒くらいかかりますが、ちゃんと動きました!
ということで、clientのdoBackgroundで例外補足したら、gearmandを起動させて、再度doBackgroundをすれば障害時にも何とかなりそうです。
workerはその際についでに生きてるか確認するか、cronで確認すればOKでしょう。
<?php function errorHandler($no, $msg, $file, $line) { throw new Exception($msg, $no); } set_error_handler('errorHandler'); $client = new GearmanClient(); $client->addServer(); $time = time(); print $time."\n"; $try = 0; while ($try < 3) { $try++; try { $client->doBackground("test", $time); break; } catch (Exception $e) { print "start gearmand!\n"; system('gearmand -q libdrizzle --libdrizzle-db=gearman_queue --libdrizzle-table=queue --libdrizzle-user=root -u root -d'); print "wait: ".($try*$try)."s\n"; sleep($try*$try); } } if ($client->returnCode() != GEARMAN_SUCCESS) { print "faild add job!\n"; }
$ php client.php 1294804988 start gearmand! wait: 1s
わーい入れれた!