2
1

Elasticache RedisとSocket.ioを用いたWebSocket通信の問題解決

Last updated at Posted at 2024-08-01

はじめに

今回は、socket.io,redis,ioredisを使用してWebSocket通信を行うシステムのインフラ作成時に、はまったポイントを備忘録を兼ねて紹介していきます

システム構成

フロントエンド

Vue.js:ユーザーインターフェースと管理インターフェース。
S3:静的ファイルのホスティング。
CloudFront:グローバルキャッシュと配信。

バックエンド

Nest.js:APIサーバー。
ECS(Elastic Container Service):コンテナオーケストレーション。

その他のAWSサービス

ALB(Application Load Balancer):リクエストをECSタスクにルーティング。
ECR(Elastic Container Registry):Dockerイメージの格納と管理。

Socket.ioを用いてWebSocket通信を行う際、以下のような構成にしました:

  1. ElastiCache Redisを使ったPub/Subシステムを実装し、複数のECSタスク間でリアルタイム通信を実現。
  2. albのSticky Sessionを有効にし、ユーザーのWebSocket接続が同じECSタスクに留まるように設定。

問題の詳細

一つ目の問題:ElastiCache Redisとの接続ができない

バックエンドのRedis設定を以下のようにしていました。

import { ConfigService } from "@nestjs/config";
import { Redis, RedisOptions } from "ioredis";

const host = this.configService.get<string>('REDIS_HOST')
const redisOptions: RedisOptions = {
    host,
    port: 6379, 
}
const redisClient = new Redis(redisOptions);

この設定はローカル環境では動作しますが、ECSとElastiCache Redisの疎通ができませんでした。原因は、ElastiCache Redisクラスタへの接続にTLSが必要だったことです。AWSのElastiCache Redisは、セキュリティのためにTLSを使用してデータを暗号化します。ローカル環境ではTLSが必要ありませんが、本番環境ではTLSが必須です。

本番環境でのみTLS設定を追加することで、ECS環境でもElastiCache Redisに接続できるようになりました。

const host = this.configService.get<string>('REDIS_HOST')
const redisTls = process.env.NODE_ENV === 'production' ? {} : false
const redisOptions: RedisOptions = {
    host,
    port: 6379, 
    tls: redisTls
}
const redisClient = new Redis(redisOptions);

二つ目の問題:WebSocketのコネクションの確立がうまくいかない

ALBのセッション永続化(sticy session)を利用していました。ALBのセッション永続化は、クライアントが接続するサーバーを特定のCookieを通じて記憶し、同じサーバーに接続し続けることを可能にします。

しかし、Socket.ioはWebSocketの接続前にポーリングを行い、接続を確立します。このポーリングリクエストは独立しており、セッション永続化のCookie情報が含まれていません。その結果、ポーリングリクエストが異なるECSタスクに振り分けられてしまいました。

問題を解決するために以下のステップを踏みました:

  1. セッション永続性の再設定: ALBでのセッション永続性を再確認し、適切に設定。

  2. Socket.ioの設定見直し:

    • transportsオプションでWebSocketのみを使用するように設定。
    • これにより、ポーリングを回避し、直接WebSocket接続を確立するようにしました。
const socket = io(url, {
  transports: ['websocket'],
  upgrade: false,
  autoConnect: false
});

まとめ

今回はWebSocketを使用したインフラ作成時に詰まった部分を紹介しました。
この記事が、同様の事象が発生している人の解決に役立てば幸いです。
ここまで読んでくださりありがとうございました!

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1