From 95193fa02763db79cbb9b8106de03d82bf083c06 Mon Sep 17 00:00:00 2001 From: Romain Baugue Date: Thu, 18 Apr 2019 10:50:37 +0200 Subject: [PATCH] Exhaust every request body before closing it (#5166) (#5479) From the documentation: > The default HTTP client's Transport may not > reuse HTTP/1.x "keep-alive" TCP connections if the Body is > not read to completion and closed. This effectively enable keep-alive for the fixed requests. Signed-off-by: Romain Baugue --- discovery/marathon/marathon.go | 6 +++++- documentation/examples/custom-sd/adapter-usage/main.go | 7 ++++++- .../remote_storage_adapter/opentsdb/client.go | 6 +++++- notifier/notifier.go | 7 ++++++- notifier/notifier_test.go | 3 ++- scrape/scrape.go | 6 +++++- storage/remote/client.go | 10 ++++++++-- 7 files changed, 37 insertions(+), 8 deletions(-) diff --git a/discovery/marathon/marathon.go b/discovery/marathon/marathon.go index eb954fcb6..4ebd90832 100644 --- a/discovery/marathon/marathon.go +++ b/discovery/marathon/marathon.go @@ -17,6 +17,7 @@ import ( "context" "encoding/json" "fmt" + "io" "io/ioutil" "math/rand" "net" @@ -306,7 +307,10 @@ func fetchApps(ctx context.Context, client *http.Client, url string) (*appList, if err != nil { return nil, err } - defer resp.Body.Close() + defer func() { + io.Copy(ioutil.Discard, resp.Body) + resp.Body.Close() + }() if (resp.StatusCode < 200) || (resp.StatusCode >= 300) { return nil, errors.Errorf("non 2xx status '%v' response during marathon service discovery", resp.StatusCode) diff --git a/documentation/examples/custom-sd/adapter-usage/main.go b/documentation/examples/custom-sd/adapter-usage/main.go index dcdff9264..aff9d76e0 100644 --- a/documentation/examples/custom-sd/adapter-usage/main.go +++ b/documentation/examples/custom-sd/adapter-usage/main.go @@ -17,6 +17,8 @@ import ( "context" "encoding/json" "fmt" + "io" + "io/ioutil" "net" "net/http" "os" @@ -98,7 +100,10 @@ func (d *discovery) parseServiceNodes(resp *http.Response, name string) (*target } dec := json.NewDecoder(resp.Body) - defer resp.Body.Close() + defer func() { + io.Copy(ioutil.Discard, resp.Body) + resp.Body.Close() + }() err := dec.Decode(&nodes) if err != nil { diff --git a/documentation/examples/remote_storage/remote_storage_adapter/opentsdb/client.go b/documentation/examples/remote_storage/remote_storage_adapter/opentsdb/client.go index 8625fe0b5..5e50eb4ac 100644 --- a/documentation/examples/remote_storage/remote_storage_adapter/opentsdb/client.go +++ b/documentation/examples/remote_storage/remote_storage_adapter/opentsdb/client.go @@ -17,6 +17,7 @@ import ( "bytes" "context" "encoding/json" + "io" "io/ioutil" "math" "net/http" @@ -114,7 +115,10 @@ func (c *Client) Write(samples model.Samples) error { if err != nil { return err } - defer resp.Body.Close() + defer func() { + io.Copy(ioutil.Discard, resp.Body) + resp.Body.Close() + }() // API returns status code 204 for successful writes. // http://opentsdb.net/docs/build/html/api_http/put.html diff --git a/notifier/notifier.go b/notifier/notifier.go index 7d9f017f9..f9c83e324 100644 --- a/notifier/notifier.go +++ b/notifier/notifier.go @@ -19,6 +19,8 @@ import ( "crypto/md5" "encoding/json" "fmt" + "io" + "io/ioutil" "net" "net/http" "net/url" @@ -508,7 +510,10 @@ func (n *Manager) sendOne(ctx context.Context, c *http.Client, url string, b []b if err != nil { return err } - defer resp.Body.Close() + defer func() { + io.Copy(ioutil.Discard, resp.Body) + resp.Body.Close() + }() // Any HTTP status 2xx is OK. if resp.StatusCode/100 != 2 { diff --git a/notifier/notifier_test.go b/notifier/notifier_test.go index f23c3fb5c..1502dfda1 100644 --- a/notifier/notifier_test.go +++ b/notifier/notifier_test.go @@ -14,6 +14,7 @@ package notifier import ( + "bytes" "context" "crypto/md5" "encoding/json" @@ -224,7 +225,7 @@ func TestCustomDo(t *testing.T) { testutil.Equals(t, testURL, req.URL.String()) return &http.Response{ - Body: ioutil.NopCloser(nil), + Body: ioutil.NopCloser(bytes.NewBuffer(nil)), }, nil }, }, nil) diff --git a/scrape/scrape.go b/scrape/scrape.go index 7fabeb642..f8e01f0af 100644 --- a/scrape/scrape.go +++ b/scrape/scrape.go @@ -20,6 +20,7 @@ import ( "context" "fmt" "io" + "io/ioutil" "math" "net/http" "sync" @@ -543,7 +544,10 @@ func (s *targetScraper) scrape(ctx context.Context, w io.Writer) (string, error) if err != nil { return "", err } - defer resp.Body.Close() + defer func() { + io.Copy(ioutil.Discard, resp.Body) + resp.Body.Close() + }() if resp.StatusCode != http.StatusOK { return "", errors.Errorf("server returned HTTP status %s", resp.Status) diff --git a/storage/remote/client.go b/storage/remote/client.go index 7dc23e716..280db2d00 100644 --- a/storage/remote/client.go +++ b/storage/remote/client.go @@ -95,7 +95,10 @@ func (c *Client) Store(ctx context.Context, req []byte) error { // recoverable. return recoverableError{err} } - defer httpResp.Body.Close() + defer func() { + io.Copy(ioutil.Discard, httpResp.Body) + httpResp.Body.Close() + }() if httpResp.StatusCode/100 != 2 { scanner := bufio.NewScanner(io.LimitReader(httpResp.Body, maxErrMsgLen)) @@ -148,7 +151,10 @@ func (c *Client) Read(ctx context.Context, query *prompb.Query) (*prompb.QueryRe if err != nil { return nil, errors.Wrap(err, "error sending request") } - defer httpResp.Body.Close() + defer func() { + io.Copy(ioutil.Discard, httpResp.Body) + httpResp.Body.Close() + }() if httpResp.StatusCode/100 != 2 { return nil, errors.Errorf("server returned HTTP status %s", httpResp.Status) }