@@ -228,6 +228,13 @@ type Client struct {
228228 // By default connection duration is unlimited.
229229 MaxConnDuration time.Duration
230230
231+ // TCPKeepalivePeriod is the duration the connection needs to
232+ // remain idle before TCP starts sending keepalive probes.
233+ //
234+ // This field is only effective when TCPKeepalive is set to true.
235+ // A zero value indicates that the operating system's default setting will be used.
236+ TCPKeepalivePeriod time.Duration
237+
231238 // Maximum number of attempts for idempotent calls.
232239 //
233240 // DefaultMaxIdemponentCallAttempts is used if not set.
@@ -315,6 +322,16 @@ type Client struct {
315322
316323 // StreamResponseBody enables response body streaming.
317324 StreamResponseBody bool
325+
326+ // Whether to enable tcp keep-alive connections.
327+ //
328+ // Whether the operating system should send tcp keep-alive messages on the tcp connection.
329+ //
330+ // By default tcp keep-alive connections are disabled.
331+ //
332+ // This option is used only if default TCP dialer is used,
333+ // i.e. if Dial and DialTimeout are blank.
334+ TCPKeepalive bool
318335}
319336
320337// Get returns the status code and body of url.
@@ -527,6 +544,8 @@ func (c *Client) Do(req *Request, resp *Response) error {
527544 MaxConns : c .MaxConnsPerHost ,
528545 MaxIdleConnDuration : c .MaxIdleConnDuration ,
529546 MaxConnDuration : c .MaxConnDuration ,
547+ TCPKeepalivePeriod : c .TCPKeepalivePeriod ,
548+ TCPKeepalive : c .TCPKeepalive ,
530549 MaxIdemponentCallAttempts : c .MaxIdemponentCallAttempts ,
531550 ReadBufferSize : c .ReadBufferSize ,
532551 WriteBufferSize : c .WriteBufferSize ,
@@ -796,6 +815,13 @@ type HostClient struct {
796815 // By default will not waiting, return ErrNoFreeConns immediately
797816 MaxConnWaitTimeout time.Duration
798817
818+ // TCPKeepalivePeriod is the duration the connection needs to
819+ // remain idle before TCP starts sending keepalive probes.
820+ //
821+ // This field is only effective when TCPKeepalive is set to true.
822+ // A zero value indicates that the operating system's default setting will be used.
823+ TCPKeepalivePeriod time.Duration
824+
799825 // Connection pool strategy. Can be either LIFO or FIFO (default).
800826 ConnPoolStrategy ConnPoolStrategyType
801827
@@ -871,6 +897,16 @@ type HostClient struct {
871897 StreamResponseBody bool
872898
873899 connsCleanerRun bool
900+
901+ // Whether to enable tcp keep-alive connections.
902+ //
903+ // Whether the operating system should send tcp keep-alive messages on the tcp connection.
904+ //
905+ // By default tcp keep-alive connections are disabled.
906+ //
907+ // This option is used only if default TCP dialer is used,
908+ // i.e. if Dial and DialTimeout are blank.
909+ TCPKeepalive bool
874910}
875911
876912type clientConn struct {
@@ -1886,6 +1922,22 @@ func (c *HostClient) dialHostHard(dialTimeout time.Duration) (conn net.Conn, err
18861922 // use dialTimeout to control the timeout of each dial. It does not work if dialTimeout is 0 or if
18871923 // c.DialTimeout has not been set and c.Dial has been set.
18881924 // attempt to dial all the available hosts before giving up.
1925+ if c .Dial == nil && c .DialTimeout == nil && c .TCPKeepalive {
1926+ d := & TCPDialer {Concurrency : defaultDialer .Concurrency , TCPKeepalive : true , TCPKeepalivePeriod : c .TCPKeepalivePeriod }
1927+ if dialTimeout > 0 {
1928+ if c .DialDualStack {
1929+ c .DialTimeout = d .DialDualStackTimeout
1930+ } else {
1931+ c .DialTimeout = d .DialTimeout
1932+ }
1933+ } else {
1934+ if c .DialDualStack {
1935+ c .Dial = d .DialDualStack
1936+ } else {
1937+ c .Dial = d .Dial
1938+ }
1939+ }
1940+ }
18891941
18901942 c .addrsLock .Lock ()
18911943 n := len (c .addrs )
@@ -2326,6 +2378,12 @@ type pipelineConnClient struct {
23262378 WriteBufferSize int
23272379 ReadTimeout time.Duration
23282380 WriteTimeout time.Duration
2381+ // TCPKeepalivePeriod is the duration the connection needs to
2382+ // remain idle before TCP starts sending keepalive probes.
2383+ //
2384+ // This field is only effective when TCPKeepalive is set to true.
2385+ // A zero value indicates that the operating system's default setting will be used.
2386+ TCPKeepalivePeriod time.Duration
23292387
23302388 chLock sync.Mutex
23312389
@@ -2335,6 +2393,15 @@ type pipelineConnClient struct {
23352393 DisableHeaderNamesNormalizing bool
23362394 DisablePathNormalizing bool
23372395 IsTLS bool
2396+ // Whether to enable tcp keep-alive connections.
2397+ //
2398+ // Whether the operating system should send tcp keep-alive messages on the tcp connection.
2399+ //
2400+ // By default tcp keep-alive connections are disabled.
2401+ //
2402+ // This option is used only if default TCP dialer is used,
2403+ // i.e. if Dial is blank.
2404+ TCPKeepalive bool
23382405}
23392406
23402407type pipelineWork struct {
@@ -2666,6 +2733,14 @@ func (c *pipelineConnClient) init() {
26662733
26672734func (c * pipelineConnClient ) worker () error {
26682735 tlsConfig := c .cachedTLSConfig ()
2736+ if c .TCPKeepalive && c .Dial == nil {
2737+ d := & TCPDialer {Concurrency : defaultDialer .Concurrency , TCPKeepalive : true , TCPKeepalivePeriod : c .TCPKeepalivePeriod }
2738+ if c .DialDualStack {
2739+ c .Dial = d .DialDualStack
2740+ } else {
2741+ c .Dial = d .Dial
2742+ }
2743+ }
26692744 conn , err := dialAddr (c .Addr , c .Dial , nil , c .DialDualStack , c .IsTLS , tlsConfig , 0 , c .WriteTimeout )
26702745 if err != nil {
26712746 return err
0 commit comments