Golang中遇到HTTP2接收GOAWAY帧时如何实现优雅关闭

Golang中遇到HTTP2接收GOAWAY帧时如何实现优雅关闭 你好,我使用 Go 的 net/http 包构建了一个 Web 应用程序。有时服务器会返回错误“http2: received GOAWAY [FrameHeader GOAWAY len=8], starting graceful shutdown”。我该如何修复它?

1 回复

更多关于Golang中遇到HTTP2接收GOAWAY帧时如何实现优雅关闭的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中处理HTTP/2 GOAWAY帧的优雅关闭,可以通过配置http.ServerIdleTimeout和实现连接状态监控来实现。当收到GOAWAY帧时,服务器会开始优雅关闭空闲连接,但不会中断活跃请求。以下是一个示例实现:

package main

import (
    "context"
    "fmt"
    "net/http"
    "time"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        time.Sleep(100 * time.Millisecond) // 模拟处理时间
        w.Write([]byte("Hello, World!"))
    })

    server := &http.Server{
        Addr: ":8080",
        Handler: mux,
        IdleTimeout: 120 * time.Second, // 空闲连接超时时间
        ReadTimeout: 10 * time.Second,  // 读取超时
        WriteTimeout: 10 * time.Second, // 写入超时
    }

    // 启动服务器
    go func() {
        if err := server.ListenAndServeTLS("cert.pem", "key.pem"); err != nil && err != http.ErrServerClosed {
            fmt.Printf("Server error: %v\n", err)
        }
    }()

    // 模拟收到GOAWAY信号后的优雅关闭
    time.Sleep(30 * time.Second) // 运行30秒后触发关闭
    
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    
    if err := server.Shutdown(ctx); err != nil {
        fmt.Printf("Graceful shutdown failed: %v\n", err)
    }
    fmt.Println("Server gracefully stopped")
}

对于客户端连接,可以配置http.Transport来更好地处理GOAWAY:

func createHTTP2Client() *http.Client {
    tr := &http.Transport{
        MaxIdleConns:        100,
        IdleConnTimeout:     90 * time.Second,
        TLSHandshakeTimeout: 10 * time.Second,
        // 启用HTTP/2
        ForceAttemptHTTP2: true,
    }
    
    return &http.Client{
        Transport: tr,
        Timeout:   30 * time.Second,
    }
}

在服务器端,可以通过监控连接状态来记录GOAWAY事件:

type connStateLogger struct{}

func (csl *connStateLogger) logState(conn net.Conn, state http.ConnState) {
    switch state {
    case http.StateIdle:
        // 记录空闲连接
    case http.StateActive:
        // 记录活跃连接
    case http.StateHijacked, http.StateClosed:
        // 记录连接关闭
    }
}

func main() {
    server := &http.Server{
        Addr: ":8080",
        ConnState: func(conn net.Conn, state http.ConnState) {
            // 记录连接状态变化
            fmt.Printf("Connection %s changed to %v\n", conn.RemoteAddr(), state)
        },
    }
}

GOAWAY帧是HTTP/2协议的正常部分,用于连接关闭前的通知。上述配置允许服务器在收到GOAWAY后完成正在处理的请求,同时拒绝新连接。

回到顶部