feat: count graceful HTTP2 goaways
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
- 新增独立 `transport/http2` 实验 Runner:支持 h2c/TLS h2、连接上限、全局请求并发闸门、GOAWAY 排空、RST_STREAM 单流取消和生命周期统计;不改变 native HTTP/1.1 默认路径。
|
- 新增独立 `transport/http2` 实验 Runner:支持 h2c/TLS h2、连接上限、全局请求并发闸门、GOAWAY 排空、RST_STREAM 单流取消和生命周期统计;不改变 native HTTP/1.1 默认路径。
|
||||||
- HTTP/2 实验 Runner 增加标准 1 MiB 头部上限、默认 8 MiB 请求体上限、128 路同连接多路复用、2 MiB 慢读取流控验收和协议错误计数;已声明超限请求在进入业务 handler 前返回 413。
|
- HTTP/2 实验 Runner 增加标准 1 MiB 头部上限、默认 8 MiB 请求体上限、128 路同连接多路复用、2 MiB 慢读取流控验收、协议错误和 GOAWAY 计数;已声明超限请求在进入业务 handler 前返回 413。
|
||||||
- 新增可配置时长的 HTTP/2 TLS soak:默认 3 秒,Linux 验收可通过 `GO_OMNI_HTTP2_SOAK_DURATION=30m` 覆盖,混合验证 128 路 stream、慢 handler、请求体、Keep-Alive 和退出回收。
|
- 新增可配置时长的 HTTP/2 TLS soak:默认 3 秒,Linux 验收可通过 `GO_OMNI_HTTP2_SOAK_DURATION=30m` 覆盖,混合验证 128 路 stream、慢 handler、请求体、Keep-Alive 和退出回收。
|
||||||
- native TLS 明确限制 ALPN 为 `http/1.1`:缺省自动宣告该协议,误配置 `h2` 等未实现协议时在启动阶段报错。
|
- native TLS 明确限制 ALPN 为 `http/1.1`:缺省自动宣告该协议,误配置 `h2` 等未实现协议时在启动阶段报错。
|
||||||
- native `Server.Stats()` 新增连接和请求过载拒绝计数;新增可信代理配置,访问日志只在 socket 对端属于配置网段时解析 `X-Forwarded-For`。
|
- native `Server.Stats()` 新增连接和请求过载拒绝计数;新增可信代理配置,访问日志只在 socket 对端属于配置网段时解析 `X-Forwarded-For`。
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ func TestShutdownSendsGoAwayAndDrains(t *testing.T) {
|
|||||||
if err := serveResult(t, done); err != nil {
|
if err := serveResult(t, done); err != nil {
|
||||||
t.Fatal(err)
|
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)
|
t.Fatalf("not drained: %+v", stats)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ type Server struct {
|
|||||||
rejectedConns atomic.Uint64
|
rejectedConns atomic.Uint64
|
||||||
rejectedReqs atomic.Uint64
|
rejectedReqs atomic.Uint64
|
||||||
protocolErrors atomic.Uint64
|
protocolErrors atomic.Uint64
|
||||||
|
goAwaySent atomic.Uint64
|
||||||
activeConns atomic.Int64
|
activeConns atomic.Int64
|
||||||
activeRequests atomic.Int64
|
activeRequests atomic.Int64
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
@@ -69,6 +70,7 @@ type Stats struct {
|
|||||||
RejectedConnections uint64 `json:"rejectedConnections"`
|
RejectedConnections uint64 `json:"rejectedConnections"`
|
||||||
RejectedRequests uint64 `json:"rejectedRequests"`
|
RejectedRequests uint64 `json:"rejectedRequests"`
|
||||||
ProtocolErrors uint64 `json:"protocolErrors"`
|
ProtocolErrors uint64 `json:"protocolErrors"`
|
||||||
|
GoAwaySent uint64 `json:"goAwaySent"`
|
||||||
ActiveConnections int64 `json:"activeConnections"`
|
ActiveConnections int64 `json:"activeConnections"`
|
||||||
ActiveRequests int64 `json:"activeRequests"`
|
ActiveRequests int64 `json:"activeRequests"`
|
||||||
}
|
}
|
||||||
@@ -93,6 +95,7 @@ func (s *Server) Stats() Stats {
|
|||||||
RejectedConnections: s.rejectedConns.Load(),
|
RejectedConnections: s.rejectedConns.Load(),
|
||||||
RejectedRequests: s.rejectedReqs.Load(),
|
RejectedRequests: s.rejectedReqs.Load(),
|
||||||
ProtocolErrors: s.protocolErrors.Load(),
|
ProtocolErrors: s.protocolErrors.Load(),
|
||||||
|
GoAwaySent: s.goAwaySent.Load(),
|
||||||
ActiveConnections: s.activeConns.Load(),
|
ActiveConnections: s.activeConns.Load(),
|
||||||
ActiveRequests: s.activeRequests.Load(),
|
ActiveRequests: s.activeRequests.Load(),
|
||||||
}
|
}
|
||||||
@@ -374,6 +377,7 @@ func (s *Server) Shutdown(ctx context.Context) error {
|
|||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
alreadyClosing := s.closing
|
||||||
s.closing = true
|
s.closing = true
|
||||||
listener := s.listener
|
listener := s.listener
|
||||||
shutdownConfig := s.shutdownConfig
|
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
|
// x/net/http2's configured shutdown callback sends GOAWAY and lets active
|
||||||
// streams finish. The base request context remains live until the timeout
|
// streams finish. The base request context remains live until the timeout
|
||||||
// path below, where connections are forcibly closed.
|
// path below, where connections are forcibly closed.
|
||||||
if shutdownConfig != nil {
|
if shutdownConfig != nil && !alreadyClosing {
|
||||||
|
s.goAwaySent.Add(uint64(len(connections)))
|
||||||
_ = shutdownConfig.Shutdown(context.Background())
|
_ = shutdownConfig.Shutdown(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 中锁住连接状态机。
|
||||||
|
|
||||||
## 进入实现前的验收矩阵
|
## 进入实现前的验收矩阵
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user