Redis・WebSocket・Vue.jsでリアルタイム通知サービスを構築する方法
Webアプリケーションを操作している最中に、リアルタイムで通知を受け取るのはごく一般的な光景です。通知はチャットボットやアラートシステムから届くこともあれば、アプリが特定のユーザー(あるいは複数のユーザー)に向けて発信するイベントによってトリガーされることもあります。通知の発生源が何であれ、近年ではRedisを活用して通知サービスを構築するケースが急速に増えています。
マイクロサービスアーキテクチャを採用した現代のアプリケーションでは、Redisはシンプルなキャッシュやプライマリデータベースとして利用されることが多いですが、それ以外にも、Redis Streamsによる永続的なメッセージングレイヤーや、有名なPub/Sub(パブリッシュ/サブスクライブ)コマンドを使った軽量なイベントシステムを通じて、サービス間の通信レイヤーとしても活躍しています。
この記事では、Redis Pub/Subを使って、Vue.js・Node.js・WebSocketで構築したWebアプリケーションへメッセージを送信する、小規模な通知サービスの作り方をわかりやすくご紹介します。
前提条件
このデモサービスでは、以下のツールを使用します。
- Docker
- Redis 5.0.x以降(本デモではRedisのDockerコンテナを使用)
- Node.js 10.x と npm(Nodeパッケージマネージャー)
- nodemon(開発中にアプリケーションを自動再起動してくれる便利ツール)
- Vue CLI
Redisサーバーの起動
まだRedisインスタンスを起動していない場合は、Dockerを使えば簡単に立ち上げられます。ターミナルで以下のコマンドを実行してください。
> docker run -it --rm --name redis-server -p 6379:6379 redis
これでRedisが起動し、接続を受け付ける準備が整いました。
Node.jsでWebSocketサーバーを作成する
まずは適切な構造でプロジェクトをセットアップしましょう。ターミナルを開いて、以下のコマンドを順番に入力します。
npmで新しいNode.jsプロジェクトを作成します(-y パラメータを付けると、すべての項目がデフォルト値に設定されます)。
最後のコマンドで、WebSocketとRedisの依存パッケージがプロジェクトに追加されます。これでコーディングの準備完了です!
WebSocketサーバーのコードを書く
お好みのコードエディター(筆者はVisual Studio Codeを使用)でプロジェクトフォルダを開きます。「code .」と入力すればカレントディレクトリを開けます。エディター内で、server.jsという名前の新規ファイルを作成してください。
このシンプルなNode.jsプログラムはデモ用途に特化しており、以下の処理に焦点を絞っています。
- Redisへの接続(9行目)
- 「app:notifications」チャネルのメッセージ購読(10行目)
- WebSocketサーバーの起動(13行目)
- ユーザークライアント接続の登録(16行目)
- Redisのサブスクライブイベントの監視(19行目)
- 全WebSocketクライアントへのメッセージ送信(21行目)
5行目と6行目は、Redisサーバーの接続先とWebSocketサーバーのポート番号を設定しているだけです。ご覧のとおり、実装は非常にシンプルです。
WebSocketサーバーの実行
nodemonをまだインストールしていない場合は、先にインストールしておきましょう。そのうえで、次のコマンドでWebSocketサーバーを起動します。
続いて、通知を受信してユーザーに表示するフロントエンドを作成していきます。
Vue.jsでフロントエンドを作成する
新しいターミナルを開き、notificationsディレクトリで以下のコマンドを実行します。
Vue CLIを未インストールの場合は、npm install -g @vue/cli を実行して先にインストールしてください。
このコマンドにより、すぐに実行・拡張可能な新しいVueプロジェクトが生成されます。
さらに、今回のデモにはBootstrapVueも必要です。人気のBootstrapフレームワークが提供するCSSライブラリやコンポーネントを、Vueから簡単に利用できるようになります。
web-clientディレクトリをエディターで開き、新しく作成したVueアプリケーションを起動しましょう。
最後のコマンドでVueの開発サーバーが起動し、ページを配信するとともに、ソースを変更すれば自動的にブラウザが再読み込みされます。
ブラウザで https://localhost:8080 にアクセスすると、デフォルトのVueウェルカムページが表示されるはずです。
フロントエンドにWebSocketを組み込む
Vueフレームワークは非常に扱いやすく、この記事ではコードをできる限りシンプルに保ちます。まずはディレクトリ構造を確認しておきましょう。
├── README.md
├── babel.config.js
├── node_modules
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
└── src
├── App.vue
├── assets
│ └── logo.png
├── components
│ └── HelloWorld.vue
└── main.js
ルートレベルの各ファイル(babel.config.js、package.json、package-lock.json、node_modules)はプロジェクトの設定に使われるものです。現時点で注目すべきは、srcディレクトリの中身です。
- main.js: アプリケーションのメインJavaScriptファイルです。共通要素を読み込み、メイン画面であるApp.vueを呼び出します。後ほどBootstrap対応のためここを編集します。
- App.vue: 特定のページやテンプレートのHTML・CSS・JavaScriptをひとつにまとめたファイルです。アプリケーションのエントリーポイントであり、デフォルトでは全画面で共有されるため、通知クライアントの処理を書くのに最適な場所です。
public/index.htmlはDOMが読み込まれる静的なエントリーポイントです。中を見ると<div id="app">があり、ここを起点としてVueアプリケーションがマウントされます。
このデモはシンプルなので、修正が必要なのはApp.vueとmain.jsの2ファイルのみです。実際のアプリケーション開発では、再利用可能なVue.jsコンポーネントとして切り出すのが良いでしょう。
WebSocketメッセージを表示するApp.vueの編集
エディターでApp.vueファイルを開き、ページ下部の</div>タグの直前に、以下のHTMLブロックを追加してください。
{{message}} という記法により、Vueに対してmessage変数の内容を画面に出力するよう指示しています。この変数は次のステップで定義します。
続いて、<script>の中身を以下のように置き換えます。
この数行のコードが担っているのは、次の2つの役割です。
- WebSocketサーバーへの接続(13行目)
- サーバーから受信したメッセージをローカルのmessage変数に反映(13〜17行目)
変更点を整理すると、以下の要素が追加されています。
- data() 関数: Vueコンポーネントに対し、画面にバインド可能なローカル変数を定義していることを示します(6〜10行目)
- created() 関数: Vueコンポーネントの初期化時に自動的に呼び出されるライフサイクルフックです
RedisからVueアプリケーションへメッセージを送信する
追加したわずかなJavaScriptのおかげで、WebSocketサーバーとVueフロントエンドは接続済みのはずです。さっそく動作を確認してみましょう!
Redis CLIまたはRedisInsightを使って、app:notificationsチャネルにメッセージをパブリッシュします。DockerでRedisを起動した場合は、次のコマンドで接続し、メッセージ送信を始められます。
ブラウザのアプリケーション下部に、送信したメッセージが表示されるはずです。
ご覧のとおり、WebSocketを使えばWebフロントエンドへのリアルタイム配信は驚くほど簡単に実現できます。次は、Bootstrapを活用してもう少し使い勝手のよいUIへと改良していきましょう。
Bootstrapでアラートブロックを作成する
このセクションでは、Bootstrapのアラートコンポーネントを利用します。新しいメッセージを受信するとアラートが表示され、シンプルなカウントダウンによって数秒後に自動的に消える仕組みです。
main.jsファイルの編集
main.jsファイルを開き、最後のimport文の後に以下の行を追記します。
この4行により、BootstrapのコンポーネントがVueアプリケーションにインポート・登録されます。
App.vueファイルの編集
App.vue内で、先ほど追加したコード(2つの<hr/>タグ間のすべてとタグ自体)を、以下のコードに置き換えます。
このコンポーネントは複数の属性を使用しています。
- id="notification": JavaScriptやCSSから要素を参照するためのID
- :show="dismissCountDown": dismissCountDown変数がnull・0でないときのみコンポーネントを表示する指定
- dismissible: ユーザーが手動で閉じられるよう、アラートに閉じるアイコンを追加
- @dismissed="dismissCountDown=0": dismissCountDownが0になった時点でアラートを閉じる挙動の指定
- @dismiss-count-down="countDownChanged": カウントダウン処理を担当するメソッド
続いて、アラートコンポーネントが使用する変数とメソッドを定義するJavaScriptを数行追加しましょう。
このセクションで実装した内容は以下のとおりです。
- data()メソッドにdismissSecsとdismissCountDown変数を追加(4〜5行目)。アラートを表示してから非表示にするまでのタイマー制御に使用します
- アラートの表示・非表示を切り替えるメソッド群を作成(10〜26行目)
- 新しいメッセージ受信時にshowAlert()メソッドを呼び出すよう変更(13行目)
それでは、実際に試してみましょう!
redis-cliまたはRedisInsightに戻り、app:notificationsチャネルに新しいメッセージを投稿してみてください。
このように、Redisを使えばアプリケーション向けの強力な通知サービスを手軽に構築できます。今回のサンプルは単一チャネル・単一サーバーで全クライアントへブロードキャストする、ごく基本形のものです。
狙いは、WebSocketとRedis Pub/Subを組み合わせて、RedisからWebアプリケーションへメッセージをプッシュする第一歩を提示することでした。実際には、複数のチャネルを活用して特定クライアントへ配信したり、スケーリングやセキュリティ対策を施したりと、発展の選択肢は無限に広がります。
また、WebSocketサーバーは逆方向にも活用できます。クライアントへプッシュするだけでなく、クライアントからのメッセージを受信することも可能です。ただしこれは別の機会に譲る大きなテーマです。今後は、Redis Gearsを使ってRedisデータベース内で直接イベントを捕捉し、各種クライアントへ配信する方法についても記事にする予定ですので、ぜひお楽しみに。
詳細については、以下のリソースも参考にしてください。
- Redis Microservices for Dummies(無料電子書籍)
- Redis Streams入門(Redis公式ドキュメント)
- Redis Pub/Sub(Redis公式ドキュメント)
- Redis Universityの無料オンライン講座
- Redis Enterprise Cloudのチェック
-
Redis SADDコマンドの使い方 – セットに要素を作成して追加する方法
このチュートリアルでは、redis-cliでSADDコマンドを使用して、キーに保存されたセット(Set)型の値に要素を作成・追加する方法を解説します。 SADDコマンドを実行すると、指定したキーがデータストア内にすでに存在する場合は、そのセットに新しい要素が追加されます(すでに存在している要素は自動的に無視されます)。一方、キーがまだ存在しない場合は、要素を追加する前に新しいセットが自動的に作成されます。 SADDコマンドの構文 redis host:port> SADD <keyname> <value1> [<value2>] 値をスペースで区切
-
Redis GEOADDコマンド徹底解説 – 地理空間データに要素を作成・追加する方法
このチュートリアルでは、Redisのキーに保存された地理空間値(geospatial value)に要素を作成・追加する方法について解説します。ここではGEOADDコマンドを使用します。 GEOADDコマンドとは GEOADDコマンドは、キーに格納された地理空間値に対して、1つ以上の地理空間メンバーを追加するためのコマンドです。地理空間値とは、このコマンドによって生成されるソート済みセット(sorted set)のことであり、メンバーは後からGEORADIUSやGEORADIUSBYMEMBERコマンドによる半径検索で取得できる形式で格納されます。 ソート済みセットへの登録には「Geohash