ホームページ >バックエンド開発 >Golang >Go リスニング サーバーを正常にシャットダウンするにはどうすればよいですか?

Go リスニング サーバーを正常にシャットダウンするにはどうすればよいですか?

Patricia Arquette
Patricia Arquetteオリジナル
2024-12-24 03:15:12622ブラウズ

How to Gracefully Shut Down a Go Listening Server?

Go でリスニング サーバーを正常に停止する方法

Go では listen.Accept 関数が実行をブロックするため、サーバーを終了するのが困難になります。サーバーを正常にリスニングします。サーバーをいつ終了するかを決定するための 1 つの方法は、リッスンしているソケットを閉じて、閉じられたネットワーク接続を示す特定のエラーを検出することです。ただし、このエラーはネット パッケージによってエクスポートされないため、開発者は厄介なエラー処理に頼ることになります。

幸いなことに、より洗練された解決策があります。完了チャネルを利用すると、接続を閉じる前にサーバーに停止するよう信号を送ることができます。サンプル コードを使用して実装する方法は次のとおりです。

package main

import (
    "io"
    "log"
    "net"
    "sync"
    "time"
)

// Echo server struct
type EchoServer struct {
    listen net.Listener
    done   sync.WaitGroup
}

// Respond to incoming connection
//
// Write the address connected to then echo
func (es *EchoServer) respond(remote *net.TCPConn) {
    defer remote.Close()
    _, err := io.Copy(remote, remote)
    if err != nil {
        log.Printf("Error: %s", err)
    }
}

// Listen for incoming connections
func (es *EchoServer) serve() {
    for {
        conn, err := es.listen.Accept()
        if err != nil {
            select {
            case <-es.done:
                // Server has been stopped, so we can exit without showing the error.
            default:
                log.Printf("Accept failed: %v", err)
            }
            return
        }
        es.done.Add(1) // Increment the waitgroup for each incoming connection
        go func() {
            es.respond(conn.(*net.TCPConn))
            es.done.Done() // Decrement the waitgroup when done handling the connection
        }()
    }
}

// Stop the server by closing the listening listen
func (es *EchoServer) stop() {
    es.done.Wait() // Wait for all outstanding connections to finish handling
    es.listen.Close() // Now it the Accept will have an error above
}

// Make a new echo server
func NewEchoServer(address string) *EchoServer {
    listen, err := net.Listen("tcp", address)
    if err != nil {
        log.Fatalf("Failed to open listening socket: %s", err)
    }
    es := &amp;EchoServer{
        listen: listen,
    }
    es.done.Add(1)
    go es.serve()
    return es
}

// Main
func main() {
    log.Println("Starting echo server")
    es := NewEchoServer("127.0.0.1:18081")
    // Run the server for 1 second
    time.Sleep(1 * time.Second)
    // Close the server
    log.Println("Stopping echo server")
    es.stop()
}

このコードでは、serve 関数は、done チャネルで値を受信したときに戻ることによってサーバーを正常に終了します。 main 関数は、サーバーを起動し、接続を待機し、正常に終了する方法を示します。 Done チャネルを利用することで、エラー処理がシャットダウン ロジックから明確に分離され、より保守しやすくエラーのないサーバーが実現します。

以上がGo リスニング サーバーを正常にシャットダウンするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。