Skip to content

feat: add stateful HTTP/3 negotiation with probe and cooldown#3281

Open
zbchi wants to merge 8 commits intoapache:developfrom
zbchi:feat/http3-negotiation-fallback
Open

feat: add stateful HTTP/3 negotiation with probe and cooldown#3281
zbchi wants to merge 8 commits intoapache:developfrom
zbchi:feat/http3-negotiation-fallback

Conversation

@zbchi
Copy link
Copy Markdown
Contributor

@zbchi zbchi commented Mar 27, 2026

Description

Before

#3266
If HTTP/3 failed, the client could then fall back to HTTP/2 with the same http.Request.
That behavior is risky for Triple, because request bodies come from io.Pipe or other non-replayable streams.
It also means a broken HTTP/3 path can keep being retried instead of letting the client stay on the healthy HTTP/2 path.

After

The client now keeps HTTP/2 as the stable path, learns about HTTP/3 from Alt-Svc on HTTP/2 responses, and validates the HTTP/3 path with an independent probe before switching later requests. Once HTTP/3 is known to be healthy, future requests may use it. If HTTP/3 later fails, the client does not replay the current request on HTTP/2; instead, it marks the HTTP/3 path unhealthy, enters cooldown, and keeps subsequent requests on HTTP/2 until it is time to probe again.

This is also closer to the approach used in dubbo: treat HTTP/3 as an upgrade that must be validated out of band, rather than retrying the current business request across transports.

in short, the behavior now is :

  1. HTTP/2 remains the default and stable path.
  2. Alt-Svc on HTTP/2 responses makes the origin a candidate for HTTP/3.
  3. An independent HTTP/3 probe (OPTIONS /) is used to validate the path.
  4. Only future requests switch to HTTP/3 after the probe succeeds.
  5. If an HTTP/3 business request fails, the current request is not replayed on HTTP/2.
  6. Failed HTTP/3 paths enter cooldown so the client does not keep retrying them immediately.
  7. Caller-driven context cancellation/deadline errors do not mark the HTTP/3 path as unhealthy.

Checklist

  • I confirm the target branch is develop
  • Code has passed local testing
  • I have added tests that prove my fix is effective or that my feature works

@zbchi zbchi changed the title Feat/http3 negotiation fallback feat: add stateful HTTP/3 negotiation with probe and cooldown Mar 27, 2026
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 27, 2026

Codecov Report

❌ Patch coverage is 76.54321% with 38 lines in your changes missing coverage. Please review.
✅ Project coverage is 49.60%. Comparing base (fb8eff2) to head (74823c4).
⚠️ Report is 1 commits behind head on develop.

Files with missing lines Patch % Lines
protocol/triple/dual_transport.go 77.35% 25 Missing and 11 partials ⚠️
protocol/triple/triple_protocol/negotiation.go 33.33% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #3281      +/-   ##
===========================================
+ Coverage    48.96%   49.60%   +0.63%     
===========================================
  Files          467      470       +3     
  Lines        34006    34694     +688     
===========================================
+ Hits         16652    17210     +558     
- Misses       16019    16091      +72     
- Partials      1335     1393      +58     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Alanxtl Alanxtl added ✏️ Feature 3.3.2 version 3.3.2 labels Mar 28, 2026
@Alanxtl Alanxtl linked an issue Mar 28, 2026 that may be closed by this pull request
2 tasks
Copy link
Copy Markdown
Contributor

@AlexStocks AlexStocks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: feat: add stateful HTTP/3 negotiation with probe and cooldown

评价

设计思路清晰,HTTP/3 探测和冷却机制实现合理。通过独立 probe 请求验证 HTTP/3 可用性,避免了在业务请求上重试带来的数据完整性问题。

[P1] 规范级问题

1. protocol/triple/dual_transport.go:95-108 - 状态机可读性

shouldUseH3 方法使用 originMode 枚举值直接比较,建议使用更具表达力的方式:

// 建议定义状态常量
const (
    stateUnknown originMode = iota
    stateCandidate
    stateProbing
    stateH3Healthy
    stateCooldown
)

func (dt *dualTransport) shouldUseH3(host string) bool {
    // 使用状态常量提高可读性
    switch dt.state.mode {
    case stateH3Healthy:
        return true
    case stateCooldown:
        // ...
    }
}

2. 测试覆盖

protocol/triple/dual_transport_test.go 测试了主要场景,但缺少:

  • Probe timeout 后立即重试的场景
  • 并发请求时的状态一致性
  • HTTP/3 连接池复用测试

3. 缺少连接池管理说明

代码中每次 probe 创建新请求,建议添加对 HTTP/3 连接复用的说明或测试。

[P2] 建议级

1. 配置化超时参数

defaultH3ProbeTimeout, defaultH3BaseCooldown, defaultH3MaxCooldown 作为常量定义,建议改为可配置参数:

type DualTransportConfig struct {
    ProbeTimeout   time.Duration
    BaseCooldown   time.Duration
    MaxCooldown    time.Duration
}

总体评价:实现质量良好,解决了 HTTP/3 回退时的数据完整性问题,建议补充并发场景测试。

Copy link
Copy Markdown
Contributor

@AlexStocks AlexStocks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

开始进行代码审查,将逐条提交具体问题。

Copy link
Copy Markdown
Contributor

@AlexStocks AlexStocks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR 3281 代码审查总结

已提交 4 条具体行级评论,以下是其他关键问题:

[P0] 并发安全问题

位置: maybeStartProbe 函数
问题: 在持有锁期间修改状态后,在锁外启动 goroutine。两个并发请求可能重复启动 probe。
建议: 在锁内完成状态检查和标记,确保只有一个 goroutine 启动 probe。

[P1] 整数溢出风险

位置: nextCooldown 函数 line 441-446
问题: 指数退避计算 d *= 2 可能溢出,溢出后与 maxCooldown 比较行为未定义。
建议: 检测溢出:if next < d || next >= maxCooldown { return maxCooldown }

[P1] 测试覆盖不足

位置: dual_transport_test.go
缺少场景:

  1. 并发多请求同时触发 probe
  2. probe 超时场景
  3. cooldown 期间收到新 Alt-Svc
  4. 多次失败后 cooldown 指数增长验证

[P2] 代码冗余

  1. shouldMarkH3Failure 中 err == nil 检查冗余(调用方已保证 err != nil)
  2. markH3Success/markH3Failure 中 host 空检查冗余(调用方已保证非空)

gh 命令调用次数: 6 次

@zbchi zbchi force-pushed the feat/http3-negotiation-fallback branch from a71288f to 74823c4 Compare March 30, 2026 06:51
@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] improve HTTP/3 negotiation and fallback behavior

4 participants