feat: count graceful HTTP2 goaways

This commit is contained in:
2026-09-22 23:16:06 +08:00
parent de33eda846
commit 7e9e8aa67c
4 changed files with 9 additions and 4 deletions

View File

@@ -177,7 +177,7 @@ func TestShutdownSendsGoAwayAndDrains(t *testing.T) {
if err := serveResult(t, done); err != nil {
t.Fatal(err)
}
if stats := s.Stats(); stats.ActiveConnections != 0 || stats.ActiveRequests != 0 {
if stats := s.Stats(); stats.ActiveConnections != 0 || stats.ActiveRequests != 0 || stats.GoAwaySent != 1 {
t.Fatalf("not drained: %+v", stats)
}
}

View File

@@ -57,6 +57,7 @@ type Server struct {
rejectedConns atomic.Uint64
rejectedReqs atomic.Uint64
protocolErrors atomic.Uint64
goAwaySent atomic.Uint64
activeConns atomic.Int64
activeRequests atomic.Int64
wg sync.WaitGroup
@@ -69,6 +70,7 @@ type Stats struct {
RejectedConnections uint64 `json:"rejectedConnections"`
RejectedRequests uint64 `json:"rejectedRequests"`
ProtocolErrors uint64 `json:"protocolErrors"`
GoAwaySent uint64 `json:"goAwaySent"`
ActiveConnections int64 `json:"activeConnections"`
ActiveRequests int64 `json:"activeRequests"`
}
@@ -93,6 +95,7 @@ func (s *Server) Stats() Stats {
RejectedConnections: s.rejectedConns.Load(),
RejectedRequests: s.rejectedReqs.Load(),
ProtocolErrors: s.protocolErrors.Load(),
GoAwaySent: s.goAwaySent.Load(),
ActiveConnections: s.activeConns.Load(),
ActiveRequests: s.activeRequests.Load(),
}
@@ -374,6 +377,7 @@ func (s *Server) Shutdown(ctx context.Context) error {
s.mu.Unlock()
return nil
}
alreadyClosing := s.closing
s.closing = true
listener := s.listener
shutdownConfig := s.shutdownConfig
@@ -389,7 +393,8 @@ func (s *Server) Shutdown(ctx context.Context) error {
// x/net/http2's configured shutdown callback sends GOAWAY and lets active
// streams finish. The base request context remains live until the timeout
// path below, where connections are forcibly closed.
if shutdownConfig != nil {
if shutdownConfig != nil && !alreadyClosing {
s.goAwaySent.Add(uint64(len(connections)))
_ = shutdownConfig.Shutdown(context.Background())
}

View File

@@ -22,7 +22,7 @@
## 必须可观测的状态
HTTP/2 版本需要在 native `Stats` 之外至少记录:活动 stream、被拒绝 stream、连接级 protocol error、RST_STREAM、GOAWAY 发送次数,以及因流控或并发闸门触发的拒绝。实验 Runner 当前已通过 `ActiveRequests`、`RejectedRequests` 和 `ProtocolErrors` 暴露活动/拒绝/协议错误快照;RST_STREAM 和 GOAWAY 的独立计数仍属于进入 native 前的补齐项。计数必须是原子快照,不能在 metrics handler 中锁住连接状态机。
HTTP/2 版本需要在 native `Stats` 之外至少记录:活动 stream、被拒绝 stream、连接级 protocol error、RST_STREAM、GOAWAY 发送次数,以及因流控或并发闸门触发的拒绝。实验 Runner 当前已通过 `ActiveRequests`、`RejectedRequests`、`ProtocolErrors` 和 `GoAwaySent` 暴露活动/拒绝/协议错误/优雅关闭快照;RST_STREAM 的独立计数仍属于进入 native 前的补齐项。计数必须是原子快照,不能在 metrics handler 中锁住连接状态机。
## 进入实现前的验收矩阵