0Pricing
Go Academy · レッスン

接続管理

切断を処理します

「接続管理」は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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. WebSocketの基礎
  2. gorilla/websocketの使用
  3. メッセージのブロードキャスト
  4. 接続管理
← Go Academyに戻る