Rails 5.0からActionCableが実装されてWebsocketが簡単に利用できるようになっています。今まで、利用する機会がなかったのですが、簡単なチャット機能を実装したいと考え調査してみました。
結論といたしましては、AWS環境でActionCableを使いオートスケーリングに対応できます。しかも、簡単に!
Redisが単一障害点になる課題が合ったり、高負荷なチャットサービスを運営する場合は別途構成を検討する必要がありそうですが、障害時の同期失敗が許容できるようなチャットサービスならば十分運用できそうです。
ActionCableのサンプルを動かしてみる
ActionCableがどのようなものか理解するために、簡単なサンプルを動かしてみることにします。
Rails 5 + ActionCableで作る!シンプルなチャットアプリ(DHH氏のデモ動画より)
上記ページを参考にして試しましたがローカル環境において簡単に、1つのブラウザでWebsocketを動作させることが出来ました。つまり、ローカル環境で動作したので、次のフローには対応できそうです。
さて、次はオートスケーリングに対応したいです。Webサービスとして公開する場合は、ロードバランサを経由し、複数のサーバで処理を分散したいのですが、これをそのままwebsocketを使ったチャットに利用すると失敗します。websocketはブラウザとサーバを1対1で結びますが、複数ブラウザで同時に接続するチャットの場合、サーバが異なると「データ更新の通知」が受け取れないためです。
Redisを利用することでこの課題を解決します。
RedisのPub/Sub機能を使う
データ変更の通知を受け取れる状態で待機できる機能をSubscribe、データを待機している相手に一斉送信する機能をPublishといいます。RedisはこのPub/Sub機能を提供しています。
Pub/Sub: https://redis.io/topics/pubsub
最初は独自で実装することを考えたので、別プロセスでsubscribeするの?面倒くさくない?などと考えていました。ですが、RailsのActionCableはRedisのPub/Subに最初から対応していました!
Redisを使う設定にする場合は config/cable.yml を開いて、adapterをredisにして、urlを指定するだけです。
RailsサーバのバックグラウンドにRedisサーバを置くことで、オートスケーリングに対応したサーバ構成が取れるようになりました。また、AWSで提供されているロードバランサのApplication Load Balancerを利用すれば、Websocket通信にも対応しているので次の図のようになります。
AWSとRailsで簡単にチャット機能を作れそう、というご紹介でした。