Home > アーカイブ > 2014-08
2014-08
PhpStorm から Vagrant VM の PHP アプリケーションをリモートデバッグする(Web & CLI)
PhpStorm から Vagrant で構築した VM の PHP アプリケーションをリモートデバッグする方法です。Web アプリケーションだけでなく、CLI アプリケーションでもリモートデバッグできるように設定していきます。
VM スペック
- 192.168.33.41 を private network で設定
- PHP + Xdebug がインストール済み
- ホストと VM は、synced folder でディレクトリを共有(/path/to/src -> /share)
0. Xdebug によるリモートデバッグの仕組み
リモートデバッグを設定する前に PhpStorm と Xdebug がどのように通信するかを見ておきます。これを理解しておくと設定がスムーズです。
下記は、Xdebug の公式サイトに掲載されている図です。ここでは、左の「IDE」が PhpStormが起動しているホスト、右の「PHP/Xdebug」が Vagrant で構築した VM と考えて下さい。
VM に HTTP リクエストが来て、PHP スクリプトの実行がはじまると、PHP/Xdebug が IDE(xdebug.remote_host
で設定したホスト)に DBGP connect の通信を行います。PhpStorm ではこの通信を受け取り、以後は DBGP で相互に通信してリモートデバッグを実現します。
ここで大切なのは、PHP/Xdebug(VM)から、PhpStorm へ DBGP connect の通信が来るという点です。これは Web でも CLI でも同じで、PHP スクリプトが VM で実行されると PhpStorm へ DBGP connect が送られてきて、リモートデバッグを開始することができます。(xdebug.remote_autostart= On
を設定した場合)
もし、うまく動かない場合などは、この点を意識して調査すると良いです。
では、実際に設定を行っていきましょう。
1. VM での設定
まず、VM にインストールされている PHP にリモートデバッグ用の設定を行います。通常は、VM を構築する際に実行するプロビジョニングに以下を含めておきます。
Xdebug が必要になるので、下記のコマンドなどで、インストールしておいて下さい。
$ yum -y install php-pecl-xdebug
1-1. php.ini(xdebug.ini)
Xdebug の設定を php.ini
等で以下のように設定します。
xdebug.remote_enable = On xdebug.remote_autostart = On xdebug.remote_host = 192.168.33.1
xdebug.remote_enable
で、リモートデバッグを有効にします。xdebug.remote_autostart
を On にすることで、リモートデバッグが常に開始されるように設定します。任意のタイミングだけ開始することもできるのですが、開発環境なので、VM側では常に開始されるようにしておき、実際にデバッグを行うかどうかは PhpStorm 側で操作します。xdebug.remote_host
で、デバッグクライアントの IP を指定します。Vagrant の private network で192.168.33.xxx
を設定しているので、ホスト側の IP として192.168.33.1
を設定しています。
1-2. 環境変数
CLI アプリケーション(phpunit
コマンドでのテストを含む)でのデバッグを行うために、環境変数PHP_IDE_CONFIG
を設定します。
CLI アプリケーションを実行するユーザでPHP_IDE_CONFIG
環境変数を定義したいので、ここでは、vagrant ユーザの ~/.bashrc
に設定しておきます。
192.168.33.41
の部分には、VM の IP を指定しておきます。
export PHP_IDE_CONFIG="serverName=192.168.33.41"
もし、apache ユーザで CLI アプリケーションを実行するなら、httpd.conf 等の SetEnv
などで設定すると良いでしょう。
2. PhpStorm での設定
PhpStorm でリモートデバッグクライアントの設定を行いましょう。
2-1. PHP Remote Debug
まず、メニューの [Run] – [Edit Configurations…] をクリックして、[Run/Debug Configurations] ダイアログを開きます。
次にダイアログ左上にある [+] をクリックして、[PHP Remote Debug] を選択します。すると、下記のように PHP Remote Debug の設定フォームが表示されます。ここでリモートデバッグの設定を入力していきます。
Name には、この設定の名称を指定します。ここではVagrant
としています。
Servers には、PHP サーバをプルダウンで選択するのですが、まだ設定が無いので、後ほど設定します。
Ide key は、今回は設定不要なのですが、何かしら値が必要なので、ダミー値を入力します。
2-2. Servers
Servers にサーバを追加するために、Servers のプルダウンメニュー横にある「…」ボタンをクリックします。クリックすると、[Servers] ダイアログが開きます。
[Servers] ダイアログでは、PHP アプリケーションが動作しているサーバの情報(ここでは Vagrant VM)を設定します。
ダイアログ左上にある [+] をクリックして、新規サーバを入力します。
Name には、名称を入力します。名称は何でも良いのですが、ここでは VM の IP を入力します。この値は、VM で設定した環境変数PHP_IDE_CONFIG
の中で記述するserverName=
の値と同じ内容にする必要があります。
Host には、VM の IP を入力します。
Use path mappings にチェックを入れます。ここでは、ローカルのファイルパスと VM でのファイルパスをマッピングを設定します。
この Vagrantfile では、ローカルの /path/to/src
を VM 上では /share
というディレクトリにマウントしているので、File/Directory
で /path/to/src
を選択し、その右にある Absolute path on server
に /share
と入力しておきます。
設定例は下記になります。
[OK] をクリックすると Servers ダイアログが閉じます。この時に [Run/Debug Configurations] では、Servers
には、現在設定したサーバが選択されています。
最後に [OK] をクリックすると、設定が保存され、ダイアログが閉じます。これで設定は完了です。
3. 動作確認
では、実際にリモートデバッグを試してみましょう。
PhpStorm でリモートデバッグを有効にするには、[Run] – [Start Listen for PHP Debug Connections] をクリックします。クリックすると [Stop Listen for PHP Debug Connections] という表示に切り替わります。この状態で、再度クリックするとリモートデバッグが停止します。
今回の設定では、VM 側は常にリモートデバッグ可能な状態になっているので、PhpStorm でのこの操作でリモートデバッグを行うかどうかを切り替えることができます。
リモートデバッグが動作しているか確認するのに、[Break at first line in PHP scripts] にもチェックを入れておきます。
3-1. Web アプリケーション
では、ブラウザから、VM にある PHP スクリプトにアクセスしてみましょう。(ここでは、Laravel アプリケーションを動かします。)
http://localhost/
にアクセスすると、処理が停止して、PhpStorm のデバッガが起動しました。
これは [Break at first line in PHP scripts] にチェックが入っているためで、一番はじめの行で処理が停止するようになっています。[Step Over] や [Step into] で、順にコードを実行して、PhpStorm 上で実行されている行が正しく遷移するか確認すると良いでしょう。
確認が終わったら、[Run…] でコードを実行する、もしくは [Stop] で停止させましょう。
3-2. CLI アプリケーション
CLI アプリケーションについてもリモートデバッグができるか確認しましょう。
vagrant ssh
で、VM にログインして、何か PHP アプリケーションをコマンドラインで起動します。ここでは php artisan
コマンドを実行します。
$ php artisan
すると、Web アプリケーションと同じく、はじめに実行される行で処理が停止し、PhpStorm のデバッガに制御が移ります。
PHPUnit なども実行して、同様になるか確認しておくと良いでしょう。
これで、Web でも CLI でも PHP アプリケーションでリモートデバッグができるようになりました。あとは順に実行するなり、任意のコードにブレイクポイントを仕掛けるなり、デバッグを行うことができます。
なお、動作確認用にチェックしておいた [Break at first line in PHP scripts] ですが、アプリケーション実行の度に停止するのは面倒なので、普段はチェックは外しておきましょう。
4. トラブルシューティング
4-1. デバッガが起動しない
おそらく基本的な設定ミスなので、手順を再確認します。
- xdebug 関連の設定変更後に Apache/php-fpm の再起動を行う
- PhpStorm で[Start Listen for PHP Debug Connections]を行う
4-2. デバッガは起動するのに、ステップ実行できない
PhpStorm の [Servers] 設定のパスマッピングの設定を見直します。
4-3. Cannot accept external Xdebug connection: Cannot parse the value of ‘$_SERVER[‘PHP_IDE_CONFIG’]’
CLI アプリケーションでリモートデバッグを行う際に発生しました。
環境変数PHP_IDE_CONFIG
が正しくセットされていなかったので、VM 側の設定を見直します。
さいごに
PhpStorm から Vagrant で構築した VM へのリモートデバッグ設定について見てきました。
はじめは面倒に見えますが、慣れてくればかなり楽に設定できます。VM 側の設定は、プロビジョニングに記述しておくと良いでしょう。
やはり、処理の流れはデバッガを使った方が掴みやすいので、ぜひ活用してみてください。
参考
http://www.jetbrains.com/phpstorm/webhelp/run-debug-configuration-php-remote-debug.html
http://www.karakaram.com/phpstorm-vagrant-remote-debug
http://blog.jetbrains.com/webide/2012/03/new-in-4-0-easier-debugging-of-remote-php-command-line-scripts/
- コメント (Close): 0
- トラックバック (Close): 0
Laravel の Queue で非同期処理を実装する(beanstalkd / IronMQ / SQS)
Laravel で実装されている Queue について見てみました。
Laravel では Queue を使うことで、時間がかかる処理や、時間差で実行したい処理を非同期で実行することができます。
Laravel 4.2 の Queue では、以下の 5 つのキュードライバをサポートしています。
- sync
- Beanstalkd
- Amazon SQS
- IronMQ
- Redis
ここでは、sync、Beanstalkd、IronMQ、Amazon SQS について試してみました。
Laravel での設定
Laravel で Queue を使うには、app/config/queue.php
にて、利用するキューエンジンの選択、設定を行います。
もちろん他の設定と同じく、app/config/local/queue.php
やapp/config/production/queue.php
など、環境に応じて設定を切り替えることも可能です。
下記が設定例です。default
では利用するキュードライバを指定します。指定できる値は、sync
, beanstalkd
, sqs
, iron
, redis
の 5 種類です。
connections
キーでは、それぞれのドライバについて接続情報を指定します。下記では、beanstalkd
の接続情報を指定しています。
return [ 'default' => 'beanstalkd', 'connections' => [ 'beanstalkd' => [ 'driver' => 'beanstalkd', 'host' => 'localhost', 'queue' => 'default', 'ttr' => 60, ], ], ];
キューへジョブを登録
キューへのジョブを登録するには、Queue
クラスのpush
メソッドを使います。
第一引数にはジョブを実行するワーカーのクラス名を、第二引数にはワーカーに渡すパラメータを指定します。
use CarbonCarbon; Queue::push('MyWorker', ['message' => 'Hello!', 'date' => Carbon::now()]);
ここでは、ワーカーのクラス名のみを指定しているため、ジョブを実行する際はfire
メソッドが呼ばれます。他にもMyWorker@doJob
とすることで任意のメソッドを実行したり、クロージャを渡して、そのクロージャをワーカーとして実行したりできます。
詳しくはドキュメントを参照してください。
http://laravel.com/docs/queues
http://laravel4.kore1server.com/docs/42/queues
ワーカーの実装
ジョブを処理するワーカーとしてMyWorker
クラスを実装します。ワーカーは特定のクラスを継承する必要はなく、 POPO(Plain Old PHP Object)で良いです。
MyWorker
クラスにはfire
メソッドを実装します。ジョブがキューに登録されると、リスナーからこのメソッドが呼ばれます。
第一引数にはジョブインスタンス、第二引数では、Queue::push()
の第二引数で指定したパラメータが渡されます。ただ、このパラメータはジョブに入る時にjson_encode()
されるので、オブジェクトのインスタンスはプロパティの連想配列となります。
下記の実装では、渡されたパラメータを元に文字列を生成して、echo
で標準出力へ出力しているだけです。
ジョブが正常に完了したら、delete()
メソッドで、ジョブを削除しておきます。これを行わないと同じジョブが何度も実行されています。
<?php use CarbonCarbon; use IlluminateQueueJobsJob; class MyWorker { /** * @param Job $job * @param array $data */ public function fire(Job $job, array $data) { echo sprintf('[%s] %s at %s', Carbon::now(), $data['message'], $data['date']['date']) . PHP_EOL; $job->delete(); } }
キューの監視
キューを監視してワーカーを起動するリスナーを起動します。
Laravel では artisan コマンドですでに用意されているのでこれを利用します。
php artisan queue:listen
コマンドを実行すると、キューを監視状態になります。この状態でキューにジョブが登録されていると、自動でワーカーが起動して処理が実行されます。
$ php artisan queue:listen
この状態でジョブが登録されると下記のように出力されます。
$ php artisan queue:listen [2014-08-14 16:52:35] Hello! at 2014-08-14 16:52:34.000000 Processed: MyWorker
このプロセスが終了しているとキューにジョブが登録されても実行されないので、supervisor や monit などで常時起動するように設定しておくと良いでしょう。
一定時間後に実行するジョブ
Queue::push()
で登録したジョブは、リスナーが感知するとワーカーが起動して実行されます。
それとは別に、Queue::later()
というメソッドを使うと、一定時間経過後に実行するジョブを登録することができます。
第一引数には、ジョブの実行を開始する時間を指定します。数値を渡すと秒数として認識され、その秒数が経過した際にジョブが実行されます。Carbon
クラスのインスタンスを渡すとCarbon
クラスで指定された日時に実行されるジョブとして登録されます。
第二引数と第三引数は、Queue::push()
の第一引数と第二引数と同じです。
下記の例では、10秒後に実行されるジョブを登録しています。
Queue::later(10, 'MyWorker', ['message' => 'Delayed', 'date' => Carbon::now()]);
リスナー側では下記のような出力になります。[]
内の日時と、at
の後ろの日時で 10 秒ずれていることが分かります。
$ php artisan queue:listen [2014-08-14 16:52:45] Delayed at 2014-08-14 16:52:34.000000 Processed: MyWorker
これはローカルの beanstalkd での実行なのでずれが無いですが、IronMQ を利用した際は、数秒のずれがありました。多少のずれは発生するので、それを認識した上で利用すると良いでしょう。
サポートしているキュードライバ
Laravel でサポートしているキュードライバ(Redisを除く)を見てみましょう。
sync
デフォルトで指定されているドライバです。
仕組みとしてはキュー、ワーカーの流れを通るのですが、ジョブが登録されると、即時にワーカーが実行されます。
非同期処理にはならないので、実際にキューを使う場面では、他のドライバを利用する必要があります。
Beanstalkd
Beanstalkd は、オープンソースのキューイングシステムです。
利用するには、Beanstalkd 自体のインストールが必要になります。
Beanstalkd は、yum などパッケージでも公開されているので、利用するプラットフォームごとに選択してインストールすると良いです。
ここでは OSX 環境を想定して、Homebrew でインストールします。
$ brew install beanstalkd
beanstalkd を起動します。デフォルトではポート11300
で待ち受けます。
$ beanstalkd
なお、beanstalkd は、デフォルトではキューの情報を永続化しません。このままだと beanstalkd が落ちるとキューの情報が消えてしまうので、本番環境などで運用する際は、永続化するように設定を行うのが良いです。
http://kr.github.io/beanstalkd/
Laravel で利用する際は、composer で下記のパッケージを追加しておきます。pda/pheanstalk
は、3.x がリリースされていますが、Laravel 4.2 は、2.x 系にしか対応していないので、バージョン番号に注意して下さい。
"require": { "pda/pheanstalk": "~2.1.0" }
IronMQ
Iron.io が提供しているメッセージキューサービスです。
ブラウザから登録するだけで利用することができます。基本は有償サービスなのですが、無料プランが用意されており、1,000,000APIリクエスト/月まで利用することができます。
グラフィカルな管理画面が用意されており、キューの状況などが分かりやすいのが良いです。
Heroku の Addon としても提供されているので、Heroku へデプロイするなら簡単に連携することができます。
Laravel で利用する際は、composer で下記のパッケージを追加しておきます。
"require": { "iron-io/iron_mq": "~1.5.1" }
下記が Heroku 環境で IronMQ を利用する際の設定例です。Heroku では、接続情報が環境変数で提供されてるので、それらをtoken
とproject
に設定しています。
return [ 'default' => 'iron', 'connections' => [ 'iron' => [ 'driver' => 'iron', 'host' => 'mq-aws-us-east-1.iron.io', 'token' => getenv('IRON_MQ_TOKEN'), 'project' => getenv('IRON_MQ_PROJECT_ID'), 'queue' => 'sample', 'encrypt' => true, ], ], ];
AWS US-East
、AWS EU-West
、Rackspace ORD
、Rackspace LON
のインスタンスを利用することができます。日本国内のインスタンスは存在しないので、国内のアプリケーションからキューを登録する場合はレイテンシが気になるかもしれません。
SQS
AWS のメッセージキューサービスです。
こちらも管理画面からキューを作成するだけで利用することができます。有償サービスですが、無料枠が用意されており、100万件キューイングリクエスト/月まで無料で利用することができます。
東京リージョンを利用できるので、アプリケーションサーバが国内にあるなら利用しやすいですね。
Laravel で利用する際は、composer で下記のパッケージを追加しておきます。
"require": { "aws/aws-sdk-php-laravel": "1.*" }
設定例は下記です。ここでは、アクセスキーやシークレット、エンドポイントURL を環境変数で渡しています。AWS ではおなじみですが、region
にキューを作成したリージョンを指定するのを忘れないようにしましょう。
'default' => 'sqs', 'connections' => [ 'sqs' => [ 'driver' => 'sqs', 'key' => getenv('AWS_ACCESS_KEY_ID'), 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), 'queue' => getenv('AWS_SQS_URL'), 'region' => 'ap-northeast-1', ], ],
ユニットテスト
キューにジョブを登録する側のテストについてです。
Queue
クラスをshouldReceive
メソッドでモック化して、テストするのが手軽です。
<?php use CarbonCarbon; /** * Class QueueTest */ class QueueTest extends TestCase { /** * @test */ public function queuePush() { $now = Carbon::create(2014, 8, 13, 12, 34, 56); Carbon::setTestNow($now); Queue::shouldReceive('connected')->once(); Queue::shouldReceive('push')->once()->with('MyWorker', ['message' => 'Hello!', 'date' => $now]); Queue::shouldReceive('later')->once()->with(10, 'MyWorker', ['message' => 'Delayed', 'date' => $now]); $this->client->request('GET', '/queue/push'); $this->assertTrue($this->client->getResponse()->isOk()); } }
サンプルアプリケーション(Heroku)
このエントリの内容を実装したサンプルアプリケーションを github に公開しています。
コード自体はシンプルで、http://localhost/quque/push
にアクセスするとジョブがキューに登録されます。あとは php artisan queue:listen
コマンドでジョブが実行されます。
Heroku で試せるように、heroku_create というシェルスクリプトで、heroku 関連のコマンドを記述しています。このコマンドを流せば、Heroku アプリケーションが構築されます。
Heroku でのポイントは、`Procfile`で、ワーカープロセスとしてリスナーを起動するという点です。
web: vendor/bin/heroku-php-apache2 public/
worker: php artisan queue:listen
このアプリケーションを Heroku にデプロイすると、web(ジョブをキューに登録する側)、worker(リスナー)の Dyno が構築されます。
あとは Heroku の管理画面で worker の Dyno 数を 1 にすると、web 経由で登録したジョブが worker によって実行されるようになります。
https://github.com/shin1x1/laravel-queue-sample
さいごに
Laravel の Queue について見てきました。
最後に、どのドライバを使うかについてですが、開発環境では beanstalkd を利用するのが手軽で良いでしょう。ローカルにインストールするので動作も速いです。
本番環境では、要件によりけりですが、国内にアプリケーションサーバがあるなら SQS、Heroku など US リージョンを利用するなら IronMQ が良さそうです。
もちろん、自前で beantalkd や Redis を立てるのも良いですが、利用できるなら、ありものを利用するのが楽ですね。
このように、開発環境と本番環境とでドライバを変えても、コード側は一切変更する必要が無いというのは、よく出来ていますね。
参考
blog.ISHINAO.net | Laravel 4でキューを使ってみる
laravel – キュードライバにbeanstalkdを使用する – Qiita
- コメント (Close): 0
- トラックバック (Close): 0
Home > アーカイブ > 2014-08
- 検索
- フィード
- メタ情報