Skip to content

Commit f1a1fcd

Browse files
grpc: disable and document overrides of OS default TCP keepalive by Go (#6672)
Co-authored-by: Arvind Bright <[email protected]>
1 parent 338d8f1 commit f1a1fcd

File tree

5 files changed

+24
-3
lines changed

5 files changed

+24
-3
lines changed

benchmark/benchmain/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ func makeClients(bf stats.Features) ([]testgrpc.BenchmarkServiceClient, func())
374374
logger.Fatalf("Failed to listen: %v", err)
375375
}
376376
opts = append(opts, grpc.WithContextDialer(func(ctx context.Context, address string) (net.Conn, error) {
377-
return nw.ContextDialer((&net.Dialer{}).DialContext)(ctx, "tcp", lis.Addr().String())
377+
return nw.ContextDialer((&net.Dialer{KeepAlive: time.Duration(-1)}).DialContext)(ctx, "tcp", lis.Addr().String())
378378
}))
379379
}
380380
lis = nw.Listener(lis)

dialoptions.go

+9
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,15 @@ func WithTimeout(d time.Duration) DialOption {
414414
// connections. If FailOnNonTempDialError() is set to true, and an error is
415415
// returned by f, gRPC checks the error's Temporary() method to decide if it
416416
// should try to reconnect to the network address.
417+
//
418+
// Note: As of Go 1.21, the standard library overrides the OS defaults for
419+
// TCP keepalive time and interval to 15s.
420+
// To retain OS defaults, use a net.Dialer with the KeepAlive field set to a
421+
// negative value.
422+
//
423+
// For more information, please see [issue 23459] in the Go github repo.
424+
//
425+
// [issue 23459]: https://github.com/golang/go/issues/23459
417426
func WithContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption {
418427
return newFuncDialOption(func(o *dialOptions) {
419428
o.copts.Dialer = f

internal/transport/http2_client.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,9 @@ func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error
176176
if networkType == "tcp" && useProxy {
177177
return proxyDial(ctx, address, grpcUA)
178178
}
179-
return (&net.Dialer{}).DialContext(ctx, networkType, address)
179+
// KeepAlive is set to a negative value to prevent Go's override of the TCP
180+
// keepalive time and interval; retain the OS default.
181+
return (&net.Dialer{KeepAlive: time.Duration(-1)}).DialContext(ctx, networkType, address)
180182
}
181183

182184
func isTemporary(err error) bool {

internal/transport/proxy.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"net/http"
2929
"net/http/httputil"
3030
"net/url"
31+
"time"
3132
)
3233

3334
const proxyAuthHeaderKey = "Proxy-Authorization"
@@ -122,7 +123,7 @@ func proxyDial(ctx context.Context, addr string, grpcUA string) (conn net.Conn,
122123
newAddr = proxyURL.Host
123124
}
124125

125-
conn, err = (&net.Dialer{}).DialContext(ctx, "tcp", newAddr)
126+
conn, err = (&net.Dialer{KeepAlive: time.Duration(-1)}).DialContext(ctx, "tcp", newAddr)
126127
if err != nil {
127128
return
128129
}

server.go

+9
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,15 @@ func (l *listenSocket) Close() error {
813813
// Serve returns when lis.Accept fails with fatal errors. lis will be closed when
814814
// this method returns.
815815
// Serve will return a non-nil error unless Stop or GracefulStop is called.
816+
//
817+
// Note: As of Go 1.21, the standard library overrides the OS defaults for
818+
// TCP keepalive time and interval to 15s.
819+
// To retain OS defaults, pass a net.Listener created by calling the Listen method
820+
// on a net.ListenConfig with the `KeepAlive` field set to a negative value.
821+
//
822+
// For more information, please see [issue 23459] in the Go github repo.
823+
//
824+
// [issue 23459]: https://github.com/golang/go/issues/23459
816825
func (s *Server) Serve(lis net.Listener) error {
817826
s.mu.Lock()
818827
s.printf("serving")

0 commit comments

Comments
 (0)