[Rails 5.2] ActionCable(Websocket)はAWSのオートスケーリング環境にそのまま対応できる

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で簡単にチャット機能を作れそう、というご紹介でした。