カテゴリー別アーカイブ: redis

scalaのRedisクライアントbrandoを使ってみる(その3)

PlayFramework2.2でscalaのRedisクライアントbrandoを使用する際にはちょっと注意が必要です。

brando1.0はakka2.3対応らしく、Play2.2ではまだakka2.2の対応となっているためそのままでは動きません。

仕方がないのでbrando0.3にバージョンを落として使用します。

また前回のサンプルだと、キーに値がない場合にはエラーになってしまいます。

そこでbrando0.3を少し改造します

  • brand.Brando.scala

これで使いやすくなりました

scalaのRedisクライアントbrandoを使ってみる(その2)

前回brandoを使用してRedisの値をGETできたので今回はSubscribeしてみます。

Redisサーバ側から値をプッシュし、それをPlayのWebsocketでブラウザ側に流すため用に特化しています

試行錯誤をかなりしましたが意外と単純でした。

ポイントは起動するクラスをActorとして作成し、PubSubMessageをReceiveするだけです

これだけでした。

scalaのRedisクライアントbrandoを使ってみる

ちょっとはまったのでメモ。

scalaのRedisクライアントには何種類か有ります。

http://redis.io/clients

当初scala-redisを使っていたのですが、Pub/Subする際に、内部的にスレッドを生成しているようで、大量のPub/Subを作成したい場合(数千)にはOutOfMemoryで落ちてしまいます。

そこでActorモデルのbrandoを使用してみました。

ネット上にはほとんど情報もなくちょっとはまってしまったので記録しておきます

https://github.com/chrisdinn/brando

こちらからダウンロードしてsbt packageでJarを作成します。

あとakkaが必要なので2.3をダウンロードしておきます。

いろいろと試行錯誤し以下のコードでとれました

Pub/Subとかこれから確かめます

PlayFramework+Redis+websocketでプッシュ配信(データ圧縮編)

Websocketに最近はまっています。

前回プッシュ配信をRedisのPub/Subを用いて実現した訳ですが、データ量が増えてくるとどうしても配信するデータを圧縮したくなります。

特にAWSなんかだと、従量課金となっていますので、データ転送量は少なければ少ないほど○

Websocket自体はまだデータの圧縮はサポートされていないとのことですので、自前でデータの圧縮伸長を実装してみました。

また、それだけではつまらないので、Reidsにチャンネルを作成し、ReidsのチャンネルごとにPub/Subする仕組みを入れています

図解するとちょっとわかりにくいですがこんな感じ

User別に作成したActorと、ユーザが選択したチャンネル(code1,code2,code3)別に作成したActorを別々に作成し、チャンネルがReidsから更新された際には、購読しているUserのActorへ更新をかけるという感じです

こうすることにより、チャンネル数がユーザ数より圧倒的に少ない場合には、Reidsに対するコネクションも削減でき、効率が良くなります。

  • route
  • Compress.scala

データ圧縮用に作成します。String型をZIP圧縮し、BASE64でエンコードします

  • UserActor.scala
  • Javascriptで解凍

JavaScriptでZIP解凍、Base64でコードするために↓からinfrate.js,base64.js,utf.jsなどをダウンロードしておきます。

http://www.onicos.com/staff/iz/amuse/javascript/expert/

サンプルの一式は以下においておきました

https://github.com/anagotan/play_websocket_compressed

PlayFramework+Redis+websocketでプッシュ配信を作成してみる

Websocketを使ったサンプルだとチャットが多いのですが、実際にはチャットのアプリを作ることはあまり有りません。

どちらかというとサーバ側から配信するというような用途が多いのではないでしょうか?

PlayframeworkのサンプルにはWebsocketを使ったサンプルが付属しています。

これを改造してサーバ側から配信できるように改造してみました

  • 環境
    • MacOS10.9
    • jdk1.7
    • playframework2.2
    • redis2.8.4
    • scala2.10
  • playframeworkのチャットサンプル

brewでインストールした場合にはこちらに入っているので、作業エリアにコピーしておきます

/usr/local/Cellar/play/2.2.1/libexec/samples/scala/websocket-chat/

  • unicast

一斉配信したい場合にはサンプルで採用されているbroadcastをそのまま使用してもいいのですが、今回は一対一通信で配信したいのでunicastを使用します。サンプルはこちらを参考にしました。

http://satoshi-m8a.github.io/blog/2013/05/18/scala-concurrent-unicast/

  • build.sbt

scalaからredisに接続するためにはscala-redisライブラリを使用します。そのためbuild.sbtに以下を記述します

  • conf/logger.xml

ログ出力用に追加します

  • conf/application.conf

redisの接続先をconfに書いておきます

  • models/ChatRoom.scala

モデルをscala-redisのテストコードを参考に修正します

これで準備完了

  • 実行

play runで実行し、ユーザ名部分にカンマ区切りでキーを入力します。このキーはカンマ区切りで複数入力可能で、このキーがredisのキーとなります。

画面が起動したら、a,b でログインしてみます

その後Reidsのコマンドで値を送ってみます

画面にa test が表示されます