レッドス、WebSocketとのチャットアプリケーションを構築する方法を学びましょう
WebSocket
プロトコルは双方向(両方のサーバとクライアントがメッセージを交換することができる)を提供します、そして、全二重(サーバーまたはクライアントは同時にメッセージを送ることができます)は、それがチャットアプリケーションなどのリアルタイムシナリオに適している通信チャンネルに接続しました.WebSocket
サーバと相互にメッセージを交換することができます-ピアツーピアの設定に似ています.このブログでは、我々はどのようにシンプルなチャットアプリケーションを構築する方法を探る
WebSocket
and Go
. 解決策は Redis
同様に(これはすぐに).A follow-up blog post (part 2) will demonstrate how to deploy this application to Azure App Service which will communicate with Azure Redis Cache using Virtual Network integration
あなたが学びます.
SET
and PUBSUB
go-redis
クライアントgorilla WebSocket
WebSocketプロトコルの完全でテストされた実装を提供するライブラリAzure Cache for Redis クラウドで管理されたREDIS提供です
なぜRedis?
チャットアプリケーションを検討しましょう.ユーザが最初に接続するとき、対応する
WebSocket
アプリケーション内で接続が作成されます(WebSocket
そして、特定のアプリケーションインスタンスに関連付けられます.このWebSocket
接続は、ユーザー間でチャットメッセージをブロードキャストすることができます.我々は、複数のインスタンスを実行することによって我々のアプリケーション(例えば、大きなユーザーベースのアカウントを)スケールすることができます.さて、新しいユーザが入ってきた場合、新しいインスタンスに接続することができます.それで、我々は異なるユーザー(したがって、彼らのそれぞれ)でシナリオを持ちますWebSocket
接続は異なるインスタンスに関連付けられます.その結果、彼らはお互いとメッセージを交換することができなくなります-これは私たちのおもちゃのチャットアプリケーションでも受け入れられません😉Redis 多様性をサポートする多彩なキー値ですrich data structures 例えば
List
, Set
, Sorted Set
, Hash
などの機能の一つも含まれていますPubSub
発行者がREDISチャンネルにメッセージを送ることができて、加入者がこれらのチャンネル(s)の上でメッセージを聞くことができる能力を使用する能力-両方とも完全に独立していて、互いに切り離されます.これは、我々が持っている問題を解決するために使用することができます.今、代わりにWebSocket
接続のみ、我々はredisを使用することができますchannel
各チャットアプリケーションを購読することができます.したがって、WebSocket
接続は現在、すべてのアプリケーションインスタンス(および関連するチャットユーザー)がそれらを受信することを保証するREDISチャンネルを介してパイプすることができます.これについては、次の節のコードに飛び込んでください.それはavailable on Github
Please note that instead of plain
WebSocket
, you can also use technologies such as Azure SignalR that allows apps to push content updates to connected clients, such as a single page web or mobile application. As a result, clients are updated without the need to poll the server or submit new HTTP requests for updates
に沿って従って、この解決策をAzureに配備するにはMicrosoft Azure アカウント.You can grab one for free 場合は、すでにそれを持っていない!
チャットアプリケーション概要
クイックコードウォークスルーのための時間.ここに、アプリケーション構造があります.
.
├── Dockerfile
├── chat
│ ├── chat-session.go
│ └── redis.go
├── go.mod
├── go.sum
├── main.go
インmain.go
, 我々register our WebSocket
handler and start the web server - 使用されるすべてはプレーンですnet/http
パッケージ http.Handle("/chat/", http.HandlerFunc(websocketHandler))
server := http.Server{Addr: ":" + port, Handler: nil}
go func() {
err := server.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
log.Fatal("failed to start server", err)
}
}()
The WebSocket
ハンドラプロセスチャットユーザWebSocket
クライアントと新しいチャットセッションを開始します.func websocketHandler(rw http.ResponseWriter, req *http.Request) {
user := strings.TrimPrefix(req.URL.Path, "/chat/")
peer, err := upgrader.Upgrade(rw, req, nil)
if err != nil {
log.Fatal("websocket conn failed", err)
}
chatSession := chat.NewChatSession(user, peer)
chatSession.Start()
}
エーChatSession
(一部)chat/chat-session.go
) ユーザを表し、対応するWebSocket
接続(サーバ側)type ChatSession struct {
user string
peer *websocket.Conn
}
セッションが開始されると、goroutine
チャットに参加したユーザーからのメッセージを受け入れる.呼び出すことで ReadMessage()
(from websocket.Conn
) インfor
ループ.このゴジラexits
を返します.WebSocket
接続がクローズされるか、アプリケーションがシャットダウンされるctrl+c
). 要約するために、チャット・メッセージを扱うために各々のユーザーのために産卵される別々のGoroutineがあります.func (s *ChatSession) Start() {
...
go func() {
for {
_, msg, err := s.peer.ReadMessage()
if err != nil {
_, ok := err.(*websocket.CloseError)
if ok {
s.disconnect()
}
return
}
SendToChannel(fmt.Sprintf(chat, s.user, string(msg)))
}
}()
ユーザーからのメッセージが受信されるとすぐにWebSocket
を使って他のユーザにブロードキャストしますSendToChannel
一部である機能chat/redis.go
. すべてはそれをredisにメッセージを発表するpubsub
チャンネルfunc SendToChannel(msg string) {
err := client.Publish(channel, msg).Err()
if err != nil {
log.Println("could not publish to channel", err)
}
}
重要な部分はsub
(加入者)方程式の一部.それぞれの接続されたチャットユーザーのための専用ゴロウーンがあった場合とは対照的にsingle
Goroutine(アプリケーション範囲で)Redisチャンネルを購読して、メッセージを受け取り、彼らのそれぞれのサーバー側を使用しているすべてのユーザーにそれを放送してくださいWebSocket
接続.func startSubscriber() {
go func() {
sub = client.Subscribe(channel)
messages := sub.Channel()
for message := range messages {
from := strings.Split(message.Payload, ":")[0]
for user, peer := range Peers {
if from != user {
peer.WriteMessage(websocket.TextMessage, []byte(message.Payload))
}
}
}
}()
}
The subscription is ended when the application instance is shut down - this is turn terminates the channel
for-range
loop and the goroutine exits
The
startSubscriber
関数はinit()
ファンクションredis.go
. The init()
関数はRedisに接続し、接続が失敗した場合にアプリケーションが終了する.ああ!これは私たちのチャットバックエンドをフックすることができますREDISインスタンスを設定する時間です.クラウドでREDISサーバを作ろう!
キャッシュセットアップ
RedisのためのAzureキャッシュはAzureの中でホストされて、Azureの範囲内で、または、Azureの外でどんなアプリケーションにでもアクセス可能である安全な、専用のRedisキャッシュへのアクセスを提供します.
このブログの目的のために、我々はAzure Redisキャッシュを
Basic
開発/テストと非重要なワークロードに理想的な単一ノードキャッシュです.また、あなたから選択することに注意してくださいStandard
and Premium
ティアーprovide different features ranging from persistence, clustering, geo-replication, etc .私は使用されますAzure CLI インストール用.また、使用することができますAzure Cloud Shell ブラウザの人なら!
Azure Redisキャッシュインスタンスをすばやく設定するには、
az redis create
コマンド.az redis create --location westus2 --name chat-redis --resource-group chat-app-group --sku Basic --vm-size c0
Checkout "Create an Azure Cache for Redis" for a step-by-step guide
完了したら、Azure Redisキャッシュインスタンス、つまりホスト、ポート、アクセスキーに接続するために必要な情報を取得する必要があります.これはCLIを使うこともできます.
//host and (SSL) port
az redis show --name chat-redis --resource-group chat-app-group --query [hostName,sslPort] --output tsv
//primary access key
az redis list-keys --name chat-redis --resource-group chat-app-group --query [primaryKey] --output tsv
Checkout "Get the hostname, ports, and keys for Azure Cache for Redis" for a step-by-step guide
……
……レッツチャット!
シンプルなものを維持するために、アプリケーションはDocker image
まず、いくつかの環境変数を設定します.
//use port 6380 for SSL
export REDIS_HOST=[redis cache hostname as obtained from CLI]:6380
export REDIS_PASSWORD=[redis cache primary access key as obtained from CLI]
export EXT_PORT=9090
export NAME=chat1
The application uses a static port
8080
internally (for the web server). We use an external port specified byEXT_PORT
and map it to the port8080
inside our container (using-p $EXT_PORT:8080
)
Dockerコンテナを起動する
docker run --name $NAME -e REDIS_HOST=$REDIS_HOST -e REDIS_PASSWORD=$REDIS_PASSWORD -p $EXT_PORT:8080 abhirockzz/redis-chat-go
その時間は、チャットに参加する!任意のWebSocketクライアントを使用できます.私は好む wscat
端末およびChrome WebSocket extension in the browser これを使ってデモします
wscat
私の端末から.異なるユーザをシミュレートするために2つの別々の端末を開きます.//terminal 1 (user "foo")
wscat -c ws://localhost:9090/chat/foo
//terminal 2 (user "bar")
wscat -c ws://localhost:9090/chat/bar
ここでチャットの例ですfoo
and bar
foo
最初に加わって、Aを得ましたWelcome foo!
メッセージなどbar
その後入社foo
. 注意foo
が通知されたbar
参加しました.foo
and bar
前にいくつかのメッセージを交換bar
レフトfoo
についても、演習として、チャットアプリケーションの別のインスタンスを起動することができます.別のdockerコンテナを別の値でスピン
EXT_PORT
と名前.//use port 6380 for SSL
export REDIS_HOST=[redis cache host name as obtained from CLI]:6380
export REDIS_PASSWORD=[redis cache primary access key as obtained from CLI]
export EXT_PORT=9091
export NAME=chat2
docker run --name $NAME -e REDIS_HOST=$REDIS_HOST -e REDIS_PASSWORD=$REDIS_PASSWORD -p $EXT_PORT:8080 abhirockzz/redis-chat-go
今すぐ接続オンポート9091
(または選択したポート)別のユーザーをシミュレートする//user "pi"
wscat -c ws://localhost:9091/chat/pi
以来foo
がアクティブであれば、通知されます.pi
and foo
交換できるチェックレッド
REDISデータ構造を覗いて確認しましょう.あなたは
redis-cli
これは.あなたがAzure Redisキャッシュを使っているならば、私は本当に便利なものを使うことを勧めますweb based Redis console これは.私たちは
SET
名前chat-users
) アクティブユーザーを格納するSMEMBERS chat-users
あなたは結果を見るべきですfoo
and bar
現在のチャットアプリケーションに接続されていると関連するアクティブWebSocket
接続1) "foo"
2) "bar"
PubSubチャンネルについてはどうですか?PUBUSB CHANNELS
単一のチャンネルがすべてのユーザに使用されるので、REDISサーバからこの結果を得るべきです:1) "chat"
これはこのブログのポストです.パート2のために調整滞在!場合は、この便利な発見し、次のようにしてください🙌 私はあなたのフィードバックを得るのが大好きだ🙏🏻
Reference
この問題について(レッドス、WebSocketとのチャットアプリケーションを構築する方法を学びましょう), 我々は、より多くの情報をここで見つけました https://dev.to/azure/let-s-learn-how-to-to-build-a-chat-application-with-redis-websocket-and-go-5cckテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol