Skip to content

Commit 8d174fa

Browse files
committed
libraries/doltcore/remotestorage: Improve connection reuse when fetching chunks from remote storage.
Improves performance of fetches from DoltHub, sql-server, and doltlab. Improves some situations where routers and network access points do not respond well to clients which open a great number of connections to the same TCP endpoint, many of which live for a very short period of time. http.DefaultClient comes with a default MaxIdleConnsPerHost of 2. Fetching with a high number of concurrent downloads results in many connections not being reused efficiently because they cannot get back into the idle pool because it is so small. Here we increase the MaxIdleConnsPerHost to be large enough so that our active connections during a fetch will fit within it. Note: S3 limits a single HTTP connection to 100 requests, after which it is closed server-side. So currently dolt can still require a large number of new connections over the course of a pull, and the rate at which they are opened will depend on a number of factors including available throughput, round trip time resolving storage locations, etc. But this change will always be a big improvement over the old behavior.
1 parent 530b577 commit 8d174fa

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

go/libraries/doltcore/env/grpc_dial_provider.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"os"
2323
"runtime"
2424
"strings"
25+
"time"
2526
"unicode"
2627

2728
"google.golang.org/grpc"
@@ -33,6 +34,26 @@ import (
3334
"github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint"
3435
)
3536

37+
var defaultDialer = &net.Dialer{
38+
Timeout: 30 * time.Second,
39+
KeepAlive: 30 * time.Second,
40+
}
41+
42+
var defaultTransport = &http.Transport{
43+
Proxy: http.ProxyFromEnvironment,
44+
DialContext: defaultDialer.DialContext,
45+
ForceAttemptHTTP2: true,
46+
MaxIdleConns: 1024,
47+
MaxIdleConnsPerHost: 256,
48+
IdleConnTimeout: 90 * time.Second,
49+
TLSHandshakeTimeout: 10 * time.Second,
50+
ExpectContinueTimeout: 1 * time.Second,
51+
}
52+
53+
var defaultHttpFetcher grpcendpoint.HTTPFetcher = &http.Client{
54+
Transport: defaultTransport,
55+
}
56+
3657
// GRPCDialProvider implements dbfactory.GRPCDialProvider. By default, it is not able to use custom user credentials, but
3758
// if it is initialized with a DoltEnv, it will load custom user credentials from it.
3859
type GRPCDialProvider struct {
@@ -66,18 +87,18 @@ func (p GRPCDialProvider) GetGRPCDialParams(config grpcendpoint.Config) (dbfacto
6687
}
6788
}
6889

69-
var httpfetcher grpcendpoint.HTTPFetcher = http.DefaultClient
90+
var httpfetcher grpcendpoint.HTTPFetcher = defaultHttpFetcher
7091

7192
var opts []grpc.DialOption
7293
if config.TLSConfig != nil {
7394
tc := credentials.NewTLS(config.TLSConfig)
7495
opts = append(opts, grpc.WithTransportCredentials(tc))
7596

97+
transport := *defaultTransport
98+
transport.TLSClientConfig = config.TLSConfig
99+
transport.ForceAttemptHTTP2 = true
76100
httpfetcher = &http.Client{
77-
Transport: &http.Transport{
78-
TLSClientConfig: config.TLSConfig,
79-
ForceAttemptHTTP2: true,
80-
},
101+
Transport: &transport,
81102
}
82103
} else if config.Insecure {
83104
opts = append(opts, grpc.WithInsecure())
@@ -109,6 +130,7 @@ func (p GRPCDialProvider) GetGRPCDialParams(config grpcendpoint.Config) (dbfacto
109130
opts = append(opts, grpc.WithPerRPCCredentials(rpcCreds))
110131
}
111132
}
133+
112134
return dbfactory.GRPCRemoteConfig{
113135
Endpoint: endpoint,
114136
DialOptions: opts,

go/libraries/doltcore/remotestorage/chunk_store.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"errors"
2323
"fmt"
2424
"io"
25+
"net"
2526
"net/http"
2627
"net/url"
2728
"sort"
@@ -49,7 +50,25 @@ var ErrCacheCapacityExceeded = errors.New("too much data: the cache capacity has
4950

5051
var ErrUploadFailed = errors.New("upload failed")
5152

52-
var globalHttpFetcher HTTPFetcher = &http.Client{}
53+
var defaultDialer = &net.Dialer{
54+
Timeout: 30 * time.Second,
55+
KeepAlive: 30 * time.Second,
56+
}
57+
58+
var defaultTransport = &http.Transport{
59+
Proxy: http.ProxyFromEnvironment,
60+
DialContext: defaultDialer.DialContext,
61+
ForceAttemptHTTP2: true,
62+
MaxIdleConns: 1024,
63+
MaxIdleConnsPerHost: 256,
64+
IdleConnTimeout: 90 * time.Second,
65+
TLSHandshakeTimeout: 10 * time.Second,
66+
ExpectContinueTimeout: 1 * time.Second,
67+
}
68+
69+
var globalHttpFetcher HTTPFetcher = &http.Client{
70+
Transport: defaultTransport,
71+
}
5372

5473
var _ chunks.TableFileStore = (*DoltChunkStore)(nil)
5574
var _ nbs.NBSCompressedChunkStore = (*DoltChunkStore)(nil)

0 commit comments

Comments
 (0)