Skip to content

feat: add pooled connection reuse health check - #426

Open
StellarisW wants to merge 5 commits into
cloudwego:mainfrom
StellarisW:feat/pooled-conn-health-check
Open

feat: add pooled connection reuse health check#426
StellarisW wants to merge 5 commits into
cloudwego:mainfrom
StellarisW:feat/pooled-conn-health-check

Conversation

@StellarisW

@StellarisW StellarisW commented Jul 24, 2026

Copy link
Copy Markdown

Summary

Adds a Linux-only, owner-synchronized (*TCPConnection).IsHealthyForReuse(ownerWaitTimeout) probe for idle pooled client connections.

  • Keeps FDOperator ownership across the LinkBuffer inspection and a single non-consuming MSG_PEEK | MSG_DONTWAIT socket probe.
  • Treats EINTR as fail-closed instead of retrying indefinitely, so both owner acquisition and the socket probe are bounded.
  • Rejects pending buffered data, socket data, FIN/reset/other socket errors, inactive/unused operators, and the PollDetach → asynchronous OnHup lifecycle window.
  • Does not modify the public netpoll.Connection interface.
  • Does not consume application bytes.

Safety boundary

This is a pre-write eligibility check, not a reservation protocol: it rejects staleness visible while probing, but a peer may still close after this method returns and before a later write.

Functional validation

The tests are contained in this repository and use real loopback TCP connections created through NewDialer().DialConnection. The focused suite covers:

  • an idle connection with no visible inbound data;
  • a temporarily busy receive owner, where the check waits and retains a healthy connection;
  • the deterministic ioreadInputAck handoff window;
  • unread data in the socket or LinkBuffer, including verification that the probe does not consume the byte;
  • peer FIN, peer reset, local close, and a nil receiver;
  • PollDetach before asynchronous OnHup publishes the closing state;
  • a local close that begins while the probe is waiting for receive ownership;
  • a receive owner that remains busy past ownerWaitTimeout, where the check fails closed and does not leave the operator owned;
  • an interrupted (EINTR) nonblocking probe, which fails closed without retrying.

Current-head commands run with Go 1.20.14 on Linux:

go test -mod=readonly ./...

go test -race -mod=readonly -count=20 \
  -run '^TestTCPConnectionIsHealthyForReuse' .

go vet -mod=readonly ./...

The full repository test suite passed, the timeout/EINTR-focused race lane passed all 20 repetitions, and go vet ./... passed at netpoll head 598bbe1df4d1772bceb7dffbb4bce6ade86dc905.

Performance benchmark

BenchmarkTCPConnectionIsHealthyForReuseIdle is included in connection_reuse_linux_test.go. It creates one real loopback TCP pair before timing, performs one warm-up check, resets the timer, and repeatedly invokes IsHealthyForReuse(1s) on that same idle connection. Every iteration fails the benchmark if the connection is classified as unhealthy.

taskset -c 0-3 go test -mod=readonly -run '^$' \
  -bench '^BenchmarkTCPConnectionIsHealthyForReuseIdle$' \
  -benchmem -benchtime=2s -count=10 -cpu=4 .
metric 10-sample median sample range
ns/op 290.7 283.7–337.3
B/op 0 0–0
allocs/op 0 0–0

Benchmark machine

  • Debian GNU/Linux 10; Linux 5.4.143.bsk.8-amd64; x86_64
  • Intel Xeon Platinum 8336C @ 2.30 GHz
  • 32 logical CPUs visible; benchmark pinned to CPUs 0-3
  • 62.65 GiB RAM visible
  • Go 1.20.14; GOMAXPROCS=4; loopback-only traffic

This benchmark measures the healthy idle IsHealthyForReuse(1s) probe itself. It is not an application-throughput or production-network benchmark.

Related work

  • Hertz consumer PR: cloudwego/hertz#1523
  • Release order: merge and release this owner capability first, then let Hertz pin the released netpoll version and publish its consumer release.

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant