接続管理
切断を処理します
「接続管理」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。
接続は永続するとは限りません
クライアントはタブを閉じたり、Wi-Fi接続を失ったり、クラッシュしたりします。堅牢なWebSocketサーバーは切断を検出し、リソースを片付け、goroutineを解放する必要があります。そうしないと、メモリやソケットがリークします。
クローズハンドシェイク
正常な終了では、両方向にcloseフレームを送信します。gorillaでは、これがReadMessageから返るエラーとして通知され、close codeを調べることができます。
if websocket.IsCloseError(err, websocket.CloseNormalClosure) {
// graceful close
}Ping/Pongキープアライブ
ハーフオープン接続(相手が切断フレームを送らずに消失した状態)を検出するため、サーバーは定期的にping制御フレームを送信し、pongの応答を待ちます。
conn.SetPongHandler(func(string) error {
conn.SetReadDeadline(time.Now().Add(60 * time.Second))
return nil
})読み取りデッドライン
読み取りデッドラインを設定すると、応答しない相手との読み取りが永遠にブロックせず、最終的にエラーになります。pongが届くたびにデッドラインを更新します。
conn.SetReadDeadline(time.Now().Add(60 * time.Second))Pingティッカー
ライターgoroutine内のティッカーが、定期的にpingを発生させます。書き込みに失敗したら接続は切れているため、終了します。
ticker := time.NewTicker(54 * time.Second)
defer ticker.Stop()
for range ticker.C {
if err := conn.WriteMessage(websocket.PingMessage, nil); err != nil {
return
}
}終了時のクリーンアップ
読み取りループまたは書き込みループが終了したら、クライアントの登録を解除して接続を閉じます。deferを使うと、panicが発生した場合でも確実に実行できます。
defer func() {
hub.unregister <- client
conn.Close()
}()接続ごとに2つのgoroutine
標準的なパターンでは、接続ごとにreadPumpとwritePumpを実行します。一方がエラーを検出すると、もう一方を停止するクリーンアップを開始します(多くの場合はsendチャネルを閉じます)。
書き込みデッドラインも設定する
書き込みデッドラインも設定し、停止した書き込みによってgoroutineが永遠に停止しないようにします。タイムアウトした書き込みはエラーを返すため、接続を破棄します。
conn.SetWriteDeadline(time.Now().Add(10 * time.Second))サーバーのグレースフルシャットダウン
サーバーのシャットダウン時には、各クライアントにcloseフレームを送信して、短時間待機します。http.Server.Shutdownやcontextのデッドラインと組み合わせてください。
conn.WriteMessage(websocket.CloseMessage,
websocket.FormatCloseMessage(websocket.CloseGoingAway, "bye"))クライアントでの再接続
切断は通常起こるものです。クライアントには、指数バックオフによる再接続ロジックを実装してください。サーバー側では、接続と切断をそれぞれ適切に処理するだけで構いません。
実行例:タイムアウト検出の例え
WebSocketのキープアライブにはライブラリが必要です。この標準ライブラリのプログラムでは、タイマーとチャネルを使って、デッドラインに基づく生存確認をモデル化します。
package main
import (
"fmt"
"time"
)
func main() {
pong := make(chan struct{})
go func() {
time.Sleep(20 * time.Millisecond) // simulate a slow/absent peer
_ = pong // no pong sent -> dead connection
}()
select {
case <-pong:
fmt.Println("alive")
case <-time.After(10 * time.Millisecond):
fmt.Println("no pong: closing dead connection")
}
}理解度チェック
接続管理について理解度を確認しましょう。
まとめ
接続管理を学びました。
- クローズハンドシェイクを処理し、close codeを調べます
- ping/pongと読み取り・書き込みデッドラインを使って応答しない相手を検出します
- read pumpとwrite pumpを実行し、
deferで後片付けします - closeフレームを使ってグレースフルに終了し、クライアントはバックオフを取り入れて再接続します
よくある質問
「接続管理」レッスンは無料ですか?
はい。「接続管理」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。
「接続管理」で何を学びますか?
切断を処理します ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Go Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「接続管理」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このGo Academyレッスンでコードを書いて実行できますか?
はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。