Skip to content

Commit a860ebe

Browse files
author
Paulo Gomes
committed
Reuse HTTP connections in managed transport
Ensure all requests are completely processed and closed, to prove odds of the underlying connections to be reused. The transport now is pooled and reused whenever possible. Signed-off-by: Paulo Gomes <[email protected]>
1 parent 3819ac3 commit a860ebe

File tree

1 file changed

+26
-22
lines changed

1 file changed

+26
-22
lines changed

pkg/git/libgit2/managed/http.go

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,11 @@ import (
5050
"errors"
5151
"fmt"
5252
"io"
53-
"net"
5453
"net/http"
5554
"net/url"
5655
"sync"
57-
"time"
5856

57+
"github.com/fluxcd/source-controller/internal/transport"
5958
git2go "github.com/libgit2/git2go/v33"
6059
)
6160

@@ -81,7 +80,8 @@ func httpSmartSubtransportFactory(remote *git2go.Remote, transport *git2go.Trans
8180
}
8281

8382
type httpSmartSubtransport struct {
84-
transport *git2go.Transport
83+
transport *git2go.Transport
84+
httpTransport *http.Transport
8585
}
8686

8787
func (t *httpSmartSubtransport) Action(targetUrl string, action git2go.SmartServiceAction) (git2go.SmartSubtransportStream, error) {
@@ -104,25 +104,11 @@ func (t *httpSmartSubtransport) Action(targetUrl string, action git2go.SmartServ
104104
proxyFn = http.ProxyURL(parsedUrl)
105105
}
106106

107-
httpTransport := &http.Transport{
108-
// Add the proxy to the http transport.
109-
Proxy: proxyFn,
110-
111-
// Set reasonable timeouts to ensure connections are not
112-
// left open in an idle state, nor they hang indefinitely.
113-
//
114-
// These are based on the official go http.DefaultTransport:
115-
DialContext: (&net.Dialer{
116-
Timeout: 30 * time.Second,
117-
KeepAlive: 30 * time.Second,
118-
}).DialContext,
119-
MaxIdleConns: 100,
120-
IdleConnTimeout: 90 * time.Second,
121-
TLSHandshakeTimeout: 10 * time.Second,
122-
ExpectContinueTimeout: 1 * time.Second,
123-
}
107+
// reuses the http transport from a pool, or create new one on demand.
108+
t.httpTransport = transport.NewOrIdle(nil)
109+
t.httpTransport.Proxy = proxyFn
124110

125-
client, req, err := createClientRequest(targetUrl, action, httpTransport)
111+
client, req, err := createClientRequest(targetUrl, action, t.httpTransport)
126112
if err != nil {
127113
return nil, err
128114
}
@@ -291,6 +277,10 @@ func (self *httpSmartSubtransportStream) Write(buf []byte) (int, error) {
291277

292278
func (self *httpSmartSubtransportStream) Free() {
293279
if self.resp != nil {
280+
// ensure body is fully processed and closed
281+
// for increased likelihood of transport reuse in HTTP/1.x.
282+
// it should not be a problem to do this more than once.
283+
io.Copy(io.Discard, self.resp.Body)
294284
self.resp.Body.Close()
295285
}
296286
}
@@ -362,6 +352,11 @@ func (self *httpSmartSubtransportStream) sendRequest() error {
362352
// GET requests will be automatically redirected.
363353
// POST require the new destination, and also the body content.
364354
if req.Method == "POST" && resp.StatusCode >= 301 && resp.StatusCode <= 308 {
355+
// ensure body is fully processed and closed
356+
// for increased likelihood of transport reuse in HTTP/1.x.
357+
io.Copy(io.Discard, resp.Body)
358+
resp.Body.Close()
359+
365360
// The next try will go against the new destination
366361
self.req.URL, err = resp.Location()
367362
if err != nil {
@@ -371,15 +366,24 @@ func (self *httpSmartSubtransportStream) sendRequest() error {
371366
continue
372367
}
373368

369+
// for HTTP 200, the response will be cleared up by Free()
374370
if resp.StatusCode == http.StatusOK {
375371
break
376372
}
377373

374+
// ensure body is fully processed and closed
375+
// for increased likelihood of transport reuse in HTTP/1.x.
378376
io.Copy(io.Discard, resp.Body)
379-
defer resp.Body.Close()
377+
resp.Body.Close()
378+
380379
return fmt.Errorf("Unhandled HTTP error %s", resp.Status)
381380
}
382381

382+
if self.owner.httpTransport != nil {
383+
transport.Release(self.owner.httpTransport)
384+
self.owner.httpTransport = nil
385+
}
386+
383387
self.resp = resp
384388
self.sentRequest = true
385389
return nil

0 commit comments

Comments
 (0)