Azure Redis Cacheを使ってチャットシステムを作る

こんにちは。まーやです。
先日デモとして作成したシステムアーキテクチャとその概要をまとめたいと思います。
そんなに目新しいアーキテクチャではないですが、いろいろなところで使えそうなアーキテクチャです。
今回はAzureで作成しましたが、もちろんAWSとかでも作成できますよ～。
残念ながら今回は会社のシステムとして作成しているのでGitHubなどでコードの公開はできません。あしからず。(※1)

# システム概要
今回作成したのは「音楽付きチャットサービス」です。
チャットルームに入室すると入室者全員が同じ音楽を聴きながらチャットできます。
同じ音楽を聴いているので、「いまのこの部分が好きなんだよねー」とか合いの手をみんなが同じタイミングで打ち込めるのが特徴となります。
ニコニコ動画さんの音楽だけバージョンのようなイメージです。
今回はデモ版だったので接続数なんてたかが知れていますが、将来的には超大人数が接続してきても耐えうるようなシステムを用意しておきたいな、と考えて構成をたてました。
今回は音楽については、Youtubeのような外部のストリーミングサービスから持ってきて配信することにしました(※2)。

システムの形としては次の通りです。
![構成.png](https://qiita-image-store.s3.amazonaws.com/0/60850/4f3c0ff5-998a-4214-7f47-143c82145c6e.png)

- Webサーバ(Azure WebApps)：以後WebAppsと呼ぶことにします
- リアルタイムチャット用Publisher/Subscriber(Azure Redis Cache)：以後RedisPubSubと呼ぶことにします
- 会話履歴などのチャットルーム情報を保持するKVS(Azure Redis Cache)：以後RedisKVSと呼ぶことにします

です。

## システムの流れ
【入室からチャット開始まで】
1. ユーザがチャットルームへ入室すると、WebSocketをつなぎます。会話履歴や「今なんの曲を共有しているのか」「何時何分何秒から曲を流し始めたのか」などの音楽情報をRedisKVSから取得します。RedisPubSubをSubsclibeします。
2. 受け取った会話履歴を入室者に表示します。
3. 取得した音楽情報から、他のチャットルーム利用者と同じ再生情報をWebApps内Node.jsで作成します。要するに曲の早送りをして、他のユーザと同じ曲の進度にして、再生を開始します。

【チャット】
1. 誰かが文字を打ち込み、送信します。送信された文字列は発信ユーザ名と共に、RedisPubSubへPublishします。
2. 入室時に設定したsubscribeにPublishした情報が到着、チャット画面に文字を表示します

以上が想定サービスの流れです。

# 使った技術
## Web Apps
Azure Web Appsを簡単にいうと、Webアプリの公開に特化したPaaSサーバです。
Azureポータル上でポチポチするだけでJavaやTomcat(今回はNode.js)の環境を用意してくれる便利な子。Web Appsについては[以前Java女子部で発表した資料がありますのでよろしければご確認ください](http://slides.com/maaya/20160426_javajo_lt-17#/25)。Web AppsではGitを使ったデプロイができます。コマンドライン慣れしている方はとても便利だと思いますよ！Gitがわからない、ちょっととにかくアップロードしたいんだ！という方は、node_modulesもろとも規定のディレクトリ(/site/wwwroot直下)にどーんとFTPアップロードして利用することが出来ます。
ただし、FTPから上げる場合は、web.configというファイルを記述し、規定ディレクトリ(/site/wwwroot直下)に配置する必要があります。web.configをサンプルで↓に置きましたので、よろしければ参考にしてみてください。

- [web.configのサンプル](https://gist.github.com/mahya8585/4782cd56224f34313ee6368a59dcecd2)   

その他参考情報

- [Azure App Service での Node.js Web アプリの使用](https://azure.microsoft.com/ja-jp/documentation/articles/app-service-web-nodejs-get-started/)
- [Azure Websites を Node.js PaaS として使う](https://r2.ag/azure-web-sites-with-nodejs/)

そもそもNode.jsからAzure Redis Cacheを呼び出す方法がわからないよ！という方は↓に検証用サンプルコードをGitHubに置いたので、参考にしてみてくださいね。

- [Azure Redis CacheをNode.jsで使うサンプルコード](https://github.com/mahya8585/studyRedisPubSub/tree/master/nodejs)

## Azure Redis Cache
Azure Redis CacheはKVSで有名な[Redis](http://redis.io/)をクラウドサービス化したものです。
詳細は[こちらの記事](http://qiita.com/maaya8585/items/0561309d305fd63b20a5)でまとめているので、参照ください。
今回はPubSub機能とKVS機能と両方を利用しています。デモなので1台のRedisにまとめてしまってもよかったのですが、今後大きくなることを見据えて最初からPubSub用とKVS用の2台に分けた作りにしました。

### PubSub機能
情報を配信するPublish機能と情報を受け取るSubscribe機能を合わせたものです。事前に情報を受け取るSubscribeに接続しておきます(これを購読といいます)。購読しているSubscribeへ情報を送信したい場合にPublishすると、購読している人全員に情報が送られるという仕組みです。
![subscribe.png](https://qiita-image-store.s3.amazonaws.com/0/60850/0b493f8c-4f34-dbfb-31d2-09cc67281fd2.png)
![publish.png](https://qiita-image-store.s3.amazonaws.com/0/60850/40cbc13f-faa4-88ca-fa33-0f5abf7faefe.png)
Redisでは「key」というパラメータでSubscribe・publishするチャネルを指定します。
今回のシステムでは、システム上複数のチャットルームが立ち上がることが想定されますので、keyにチャットルーム名(チャットルームID）を設定し、Pub/Subさせるようにしました。

### KVS機能
KVS(Key Value Store)機能はRedisのメイン機能です。keyとvalueを1対1で保持させるNoSQL型のデータ管理手法です。
KVSのツールは様々ありますが、RedisはSet型やHash型などの豊富なデータ型が取り扱えること、挿入したデータに有効期限を設けることができ、有効期限を過ぎたデータは自動で消滅させてくれたりと便利な機能が沢山あります。

- データの更新が多い場合
- データの出し入れにスピードがもとめられる場合
- 削除までの期間が短い一時的なデータの管理をする場合

などに利用検討ができると思います。
今回は「チャットルームの情報」と「チャットルームの音楽状態」の保持に使用しました。
チャットした文字列の情報は、半永続的に取っておきたい情報ではありますが、登録・更新が頻繁に発生するのでRedisを採用しています。
全チャット情報を保持したいのであればRDSの方が断然向いていると思うのですが、今回は「最新X件のみ保持」なのでこれでよいかな・・・と。今後しっかりしたシステムになってきたらRDSへ移行検討も必要そうです。

# 将来的にやりたい構成
将来的に（本格サービスとなったときに）やりたい事、というかキチンと考えて作るべきこととして、Web Appsの前にロードバランサーを置いておく、ということが挙げられます。Web Apps自体にスケーリング機能がついていますので、スケーリングのためにロードバランサーを置いておきたい！というよりは、Blue-Greenデプロイメントをする、などの運用上の理由から必要だろうと考えています。
Azureではこの機能は[Traffic Manager](https://azure.microsoft.com/ja-jp/services/traffic-manager/)というサービスで実現ができます。Traffic ManagerもAzureのポータルからぽちぽちするだけで使うことができますので、利用は簡単です。
本サービスの開発する際はTraffic Managerを利用していきたいと思います。

# 感想
Redis のPub/Subはかなり高速に動いてくれますので、チャット以外のシステムでも色々と使えて重宝しそうです。ただ、まだデモ段階であるということから負荷試験的なことを行っていないので、利用者増加したときにどんな性能になるのか試したい、という気持ちでいっぱいです。これはAzure Redis Cacheに限らずWeb Appsなどシステム全体に言えますね。
システム構成もそんなに複雑ではないですし、履歴などをとらずにただただチャットだけ試すのであればRedisとアプリがあればそれだけでよいので、気軽に試して頂けるかと思います。

# まとめ
Azure Redis Cacheをつかったチャットシステムは簡単に作れる。


--------------------------
※1 システム概要については若干のフェイクをいれることを条件に公開許可を自社からいただきました。
※2 音楽を外部から利用する場合は利用規約や著作権についてちゃんと調べましょう・・・今回は音楽を無料で使えるサイトで用意されていた音楽ストリーミングAPIを使いました。