🏝️
GoでWebSocketを使用した通知システムを作成する:[Redis連携]
はじめに
前回の記事では、GoでWebSocketを使った基本的なリアルタイム通信を実装しました。
今回は、さらに応用的なWebSocketの活用方法として、通知システムの作成およびRedisを使ったスケーラブルなWebSocketサーバーの構築を解説します。
対象読者
- WebSocketを活用して通知システムを実装したい方
- Redisを使ってWebSocketサーバーをスケールアウトしたい方
- 複数のWebSocketクライアントを効率的に管理したい方
目次
- WebSocketを活用した通知システムの作り方
- 通知システムの仕組み
- WebSocketサーバーの実装
- クライアント側の実装(JavaScript)
- Redisを使ったWebSocketサーバーの構築方法
- Redis Pub/Subの仕組み
- GoでのRedis連携(
go-redis
) - マルチインスタンス対応のWebSocketサーバー
1. WebSocketを活用した通知システムの作り方
1.1 通知システムの仕組み
WebSocketを活用すると、サーバーからリアルタイムでクライアントに通知を送信できます。
例:通知システムの流れ
- クライアントがWebSocketに接続する
- サーバーが特定のイベント(新しい投稿、メッセージなど)を検知
- サーバーが該当ユーザーにリアルタイム通知を送信
1.2 WebSocketサーバーの実装
まず、GoでWebSocketの通知サーバーを実装します。
server.go
package main
import (
"fmt"
"net/http"
"sync"
"github.com/gorilla/websocket"
)
type Client struct {
conn *websocket.Conn
}
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true },
}
var clients = make(map[*Client]bool)
var mu sync.Mutex
func handleWebSocket(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
fmt.Println("WebSocket connection failed:", err)
return
}
client := &Client{conn: conn}
mu.Lock()
clients[client] = true
mu.Unlock()
defer func() {
mu.Lock()
delete(clients, client)
mu.Unlock()
conn.Close()
}()
for {
_, _, err := conn.ReadMessage()
if err != nil {
break
}
}
}
func sendNotification(message string) {
mu.Lock()
defer mu.Unlock()
for client := range clients {
client.conn.WriteMessage(websocket.TextMessage, []byte(message))
}
}
func main() {
http.HandleFunc("/ws", handleWebSocket)
fmt.Println("WebSocket server running on ws://localhost:8080/ws")
http.ListenAndServe(":8080", nil)
}
-
clients
マップでWebSocketに接続しているクライアントを管理 -
sendNotification()
で接続中のすべてのクライアントにメッセージを送信
1.3 クライアント側の実装(JavaScript)
index.html
<script>
const ws = new WebSocket("ws://localhost:8080/ws");
ws.onmessage = function(event) {
alert("通知: " + event.data);
};
</script>
- WebSocketからのメッセージを受け取るとポップアップ通知を表示
2. Redisを使ったWebSocketサーバーの構築方法
2.1 Redis Pub/Subの仕組み
Redis Pub/Sub(パブリッシュ・サブスクライブ)を使うと、異なるWebSocketサーバー間で通知を共有できます。
go-redis
)
2.2 GoでのRedis連携(Redisをインストール
docker run --name redis -d -p 6379:6379 redis
Goライブラリをインストール
go get github.com/go-redis/redis/v8
server_redis.go
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
"net/http"
"github.com/gorilla/websocket"
)
var ctx = context.Background()
var rdb = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
func handleWebSocket(w http.ResponseWriter, r *http.Request) {
conn, _ := upgrader.Upgrade(w, r, nil)
defer conn.Close()
sub := rdb.Subscribe(ctx, "notifications")
defer sub.Close()
ch := sub.Channel()
for msg := range ch {
conn.WriteMessage(websocket.TextMessage, []byte(msg.Payload))
}
}
func sendNotification(message string) {
rdb.Publish(ctx, "notifications", message)
}
func main() {
http.HandleFunc("/ws", handleWebSocket)
fmt.Println("WebSocket server with Redis running on ws://localhost:8080/ws")
http.ListenAndServe(":8080", nil)
}
-
rdb.Publish()
を使って通知をRedisに送信 -
rdb.Subscribe()
でRedisから通知を受信し、WebSocketでクライアントに配信
まとめ
項目 | 説明 |
---|---|
WebSocket 通知システム | Goでリアルタイム通知を実装する方法 |
Redis Pub/Sub | 異なるWebSocketサーバー間で通知を共有する方法 |
Redis によるスケールアウト | 複数サーバーでも統一的に通知を送信 |
本記事では、WebSocketを活用した通知システムと、Redisを用いたWebSocketサーバーの構築方法を解説しました。
次も発展系を勉強していこうと思います!
Discussion