ActionCableとロードバランサーを併用する時のRedisの設定


こんにちは。
Cryptogamesで働いているじゅん(@BoNingennnN)です。

最近仕事でAcitionCableを使う機会がありました。
RailsでWebsocket通信を行うものを実装するなら、ActionCableを使うのがデフォルトです。
リアルタイムのメッセージなどの機能を実装する時に使うことが多いと思います。

ActionCableは若干とっつきにくい部分もありますが、使い慣れてしまえば基本的な部分で詰まることはあまりないと思います。

ですが、Redisの設定ではかなり苦しんだので、今回はそのことを書いていきます。
(ちなみにQiitaには初めて投稿します!)

本番環境でActionCableを使うなら、Redisを使う必要がある。

「ActionCableを使ってみた」というような記事がいくつかあるかと思いますが、その多くではRedisを使っていません。
これは、development環境では初期設定としてRedisが使われていないからです。

しかし、公式のドキュメントにも書かれている通り、本番環境ではRedisを使うことが推奨されています。
なので、もしActionCableを使うようなWebアプリケーションを作って、実際に本番運用する予定があるのであれば、Redisを使う必要があります。

ロードバランサーを使わない場合

ロードバランサーを使わない場合、もしくはロードバランサーを使ったとしてもサーバーが一台の場合は、比較的シンプルです。
アプリケーションののっているEC2上にRedisもインストールすればOKです。
そしてそれを起動し、config/cable.ymlの記述を変えてあげればうまく作動します。
(イメージは下の感じ。字が汚くてすみません、、)

私も最初はこちらでやっていました。
しかし、ロードバランサーを立てて、その下に複数台のサーバーをぶら下げるような構成だと、このパターンではうまくいきません。
(サーバーとクライアントが1対1であればうまくいきます。ですが、リアルタイムメッセージのようにクライアント側が複数の場合はうまくいかない。)

これを解決するためには、RedisをEC2の外においてあげる必要があります。

ロードバランサーを使う場合の設定

ここからが本題です。
ロードバランサーがない場合と同様に、EC2にRedisを立てるとうまくいきません。
2つのクライアントが異なるEC2のサーバーとWebsocket通信をし、その上でメッセージのやり取りを行おうとすると、下の図のような感じでうまくメッセージが飛びません。

これを解決するためには、RedisをEC2の外にだしてあげることが必要となります。

(この図は、クライアントAからクライアントBにメッセージを送る時の図。)

Redis専用のEC2を立てる方法もあるかと思いますが、今回私はAWSのElastiCache Redisを使いました。
ElastiCache Redisを作成すると、プライマリエンドポイントというものが表示されます。
hogehoge.************.chache.amazonaws.com:6379
みたいなやつです。

これをconfig/cable.ymlに記述すればOKなのですが、なぜかなかなかうまくいきませんでした。
試行錯誤を繰り返した結果、最終的にどうにかうまくいったのでそれを共有します。

config/cable.yml
production:
  adapter: redis
  port: 6379
  url: redis://hogehoge.************.chache.amazonaws.com

これで設定ファイル自体はOKなはずです。
(ただし、urlについてはもちろん環境変数に入れておくべきです。)

これで本番環境でもActionCableが使える、、と言いたいところですが、もう一点気をつけないといけないことがあります。
それが作成したElastiCache Redisのセキュリティグループです。

初期設定ではRedisはPort番号6379を使います。
なので、当たり前といえば当たり前ですが、セキュリティグループのインバウンドに関しても、Port6379をあけてあげる必要があります。
アウトバウンドに関しては全てをあけて問題ないかと思います。

これでようやくちゃんと動作します!!

以上で初めてのQiitaへの投稿を終わります!
(説明が色々分かりづらくてすみません🙇‍♂️)