ですが、時には管理画面や、バッチの処理によってユーザーに何か通知をしたいことがあるかもしれません。
今度はredisを利用して、システム管理者とユーザーの間でリアルタイム通信を行なってみます。
以前紹介したFuelPHPもまた、キャッシュストアや、クライアントインターフェースとしてRedisをサポートしています。
そこで、FuelPHPで管理画面をつくり、ボタンを押すとチャット中のユーザーに管理者からのメッセージを表示させたいと思います。
チャットプログラムや構成は前々回の構成のまま、node1, node2という2つのサーバーがredisサーバーにつながってセッション共有されている状態とします。
今回は、以下のように、さらにadminサーバーを追加し、管理画面を置きます。
上図のように、fuelphpからredisにpublishしたものを同じadminサーバー上のsocket.ioでsubscribeし、チャットサーバーへブロードキャストするイメージです。
チャットサーバーが直接subscribeすることも可能ですが、そうすると、チャットサーバーの数だけsubscribe→emitが発生して、メッセージが重複してしまいます。subscribe→emit役は1つである必要があるので、adminサーバーに兼任させます。
なので、既存のチャットサーバーには手を加える必要がなく、adminサーバーだけ用意して実装すればいいわけです。
それでは実際に用意してみます。
まず必要なユーザーやライブラリを用意します。
FuelPHPの最新版(v1.4)では、タイムゾーンの指定が必至になったのでphp.iniで設定します。
次にアプリユーザーのホームディレクトリをApacheからアクセス可能にします。
アプリを作成します。
publishボタンを配置する画面(index)とpublishボタンの押下(publish)の2つのアクションを用意します。
次に、DocumentRootをFuelPHPのpublicディレクトリに向けます。
そして、Apacheの設定をシンボリックリンクをたどり、.htaccessを許可するように変更し、起動します。
次にFuelPHPのconfig/db.phpおよび、viewとcontrollerを以下のように実装します。
fuel/app/config/db.php
redisの接続先を指定します。チャットサーバーが参照しているのと同じサーバーに接続させるようにします。
fuel/app/views/greeting/index.php
Publishボタンを配置します。
fuel/app/classes/controller/greeting.php
publishアクション内で、Redisクラスをインスタンス化しています。
ここでの引数defaultは、db.phpで設定したラベルを指定します。
そして、publishメソッドを呼び出すことにより、redisサーバーに「greeting」というチャンネルでpublishを行います。
ここまでで、管理画面自体は完成です。
以下のようにPublishボタンがあるだけのシンプルな画面になっています。
つづいて、同じadminサーバーに、node.jsを入れて動かします。
モジュールはforever, socket.io, redisを入れます。
socket.ioにもredisが含まれているのですが、requireのしやすさやバージョンが新しさなどのため、別途いれておきます。
これでnodeのインストールができました。
それでは、subscribe→emit用にnodeのスクリプトを実装します。
ポイントは、チャット用のスクリプトと同じようにredisサーバーをRedisStoreとしてstore登録することと、
それとは別にsubscribe用のredisクライアントを作り、「greeting」チャンネルをsubscribeし、受信したメッセージをチャット参加者全員にemitするようにするところです。
これを起動します。
$ forever start admin.js
それでは、実際に動かしてみましょう。
まず、前回と同様、node1とnode2のチャットウィンドウを開いて、適当にチャットしてみます。
それでは、ここで先程の管理画面でPublishボタンを押してみます。
そして、チャット画面をみてみます。
おお!メッセージが表示されました。
これで管理画面からのコントロールも可能になりました。
以上です。
チャットプログラムや構成は前々回の構成のまま、node1, node2という2つのサーバーがredisサーバーにつながってセッション共有されている状態とします。
今回は、以下のように、さらにadminサーバーを追加し、管理画面を置きます。
+----------+ +---------+ | admin | | redis | |----------| pub |---------| | fuelphp +-------> | | | sub | redis | | admin.js <-------+ | +-----+----+ +---------+ | +-----------------+ | emit | +-----v----+ +----v----+ | node1 | | node2 | |----------| |---------| | chat.js | | chat.js | +----------+ +---------+
上図のように、fuelphpからredisにpublishしたものを同じadminサーバー上のsocket.ioでsubscribeし、チャットサーバーへブロードキャストするイメージです。
チャットサーバーが直接subscribeすることも可能ですが、そうすると、チャットサーバーの数だけsubscribe→emitが発生して、メッセージが重複してしまいます。subscribe→emit役は1つである必要があるので、adminサーバーに兼任させます。
なので、既存のチャットサーバーには手を加える必要がなく、adminサーバーだけ用意して実装すればいいわけです。
それでは実際に用意してみます。
まず必要なユーザーやライブラリを用意します。
# useradd appadmin # passwd appadmin # yum install -y vim git wget php gcc gcc-c++ make # curl get.fuelphp.com/oil | sh
FuelPHPの最新版(v1.4)では、タイムゾーンの指定が必至になったのでphp.iniで設定します。
# vim /etc/php.ini --- date.timezone = Asia/Tokyo --
次にアプリユーザーのホームディレクトリをApacheからアクセス可能にします。
# chmod 755 /home/appadmin
アプリを作成します。
publishボタンを配置する画面(index)とpublishボタンの押下(publish)の2つのアクションを用意します。
# su - appadmin $ oil create app $ cd app $ oil g controller greeting index publish
次に、DocumentRootをFuelPHPのpublicディレクトリに向けます。
$ exit # cd /var/www/ # mv html html.org # ln -s /home/appadmin/app/public html
そして、Apacheの設定をシンボリックリンクをたどり、.htaccessを許可するように変更し、起動します。
# vim /etc/httpd/conf/httpd.conf --- <Directory "/var/www/html"> ~略~ Options FollowSymLinks ~略~ AllowOverride All ~略~ </Directory> --- # /etc/init.d/httpd start
次にFuelPHPのconfig/db.phpおよび、viewとcontrollerを以下のように実装します。
fuel/app/config/db.php
redisの接続先を指定します。チャットサーバーが参照しているのと同じサーバーに接続させるようにします。
$ vim fuel/app/config/db.php <?php /** * Use this file to override global defaults. * * See the individual environment DB configs for specific config information. */ return array( 'redis' => array( 'default' => array( 'hostname' => '10.0.0.200', 'port' => 6379 ) ), );
fuel/app/views/greeting/index.php
Publishボタンを配置します。
$ vim fuel/app/views/greeting/index.php --- <p>Index</p> <?php echo Form::open('greeting/publish'); ?> <?php echo Form::submit('publish', 'publish'); ?> <?php echo Form::close(); ?> ---
fuel/app/classes/controller/greeting.php
publishアクション内で、Redisクラスをインスタンス化しています。
ここでの引数defaultは、db.phpで設定したラベルを指定します。
そして、publishメソッドを呼び出すことにより、redisサーバーに「greeting」というチャンネルでpublishを行います。
$ vim fuel/app/classes/controller/greeting.php --- <?php class Controller_Greeting extends Controller_Template { public function action_index() { $this->template->title = 'Greeting » Index'; $this->template->content = View::forge('greeting/index'); public function action_publish() { $redis = Redis::instance('default'); $redis->publish('greeting', 'おはよう諸君!!'); $this->template->title = 'Greeting » Publish'; $this->template->content = View::forge('greeting/publish'); } } ---
ここまでで、管理画面自体は完成です。
以下のようにPublishボタンがあるだけのシンプルな画面になっています。
つづいて、同じadminサーバーに、node.jsを入れて動かします。
モジュールはforever, socket.io, redisを入れます。
socket.ioにもredisが含まれているのですが、requireのしやすさやバージョンが新しさなどのため、別途いれておきます。
# cd /usr/local/src # wget http://nodejs.org/dist/v0.8.14/node-v0.8.14.tar.gz # tar xzvf node-v0.8.14.tar.gz # cd node-v0.8.14 # ./configure # make # make install # curl https://npmjs.org/install.sh | sh # npm install -g socket.io # npm install -g forever # npm install -g redis
これでnodeのインストールができました。
それでは、subscribe→emit用にnodeのスクリプトを実装します。
# su - appadmin $ mkdir -p /home/appadmin/admin/node $ cd /home/appadmin/admin/node $ vim admin.js --- var server = require('http').createServer(function(req, res){ res.writeHead(200, {'Content-Type': 'text/html'}); res.end('server connected'); }); server.listen(3001); var io = require('socket.io').listen(server); var RedisStore = require('socket.io/lib/stores/redis'); var opts = {host:'10.0.0.200', port:6379}; io.set('store', new RedisStore({redisPub:opts, redisSub:opts, redisClient:opts})); var redis = require('redis'); var sub = redis.createClient(opts.port, opts.host); sub.subscribe('greeting'); sub.on("message", function(channel, message){ io.sockets.emit('msg', {msg:message}); }); ---
ポイントは、チャット用のスクリプトと同じようにredisサーバーをRedisStoreとしてstore登録することと、
それとは別にsubscribe用のredisクライアントを作り、「greeting」チャンネルをsubscribeし、受信したメッセージをチャット参加者全員にemitするようにするところです。
これを起動します。
$ forever start admin.js
それでは、実際に動かしてみましょう。
まず、前回と同様、node1とnode2のチャットウィンドウを開いて、適当にチャットしてみます。
それでは、ここで先程の管理画面でPublishボタンを押してみます。
そして、チャット画面をみてみます。
おお!メッセージが表示されました。
これで管理画面からのコントロールも可能になりました。
以上です。