From 1f38dc83a17eb4e15edb79c195db909ade8ad3bb Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Fri, 3 Nov 2017 18:46:17 +0200 Subject: [PATCH] Make HTTP transport API spec property Right now Transport is created for each requests, which means that connection pooling is not used and on each request it creates new connection to the upstream server. This is differ from 2.3 behavior, which had global Transport for all APIs. During the 2.4 refactor it was changed to behavior described above. This change introduce transport caching, so it gets re-used between API calls. In addition, this is better than 2.3 approach, because each API can have different transport settings and timeouts, and now each API gets own transport. --- api_definition.go | 1 + reverse_proxy.go | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/api_definition.go b/api_definition.go index f761639954e..a2be309db32 100644 --- a/api_definition.go +++ b/api_definition.go @@ -135,6 +135,7 @@ type APISpec struct { LastGoodHostList *apidef.HostList HasRun bool ServiceRefreshInProgress bool + HTTPTransport http.RoundTripper } // APIDefinitionLoader will load an Api definition from a storage diff --git a/reverse_proxy.go b/reverse_proxy.go index de9cfea26c0..36f3db2350e 100644 --- a/reverse_proxy.go +++ b/reverse_proxy.go @@ -436,8 +436,10 @@ func httpTransport(timeOut int, rw http.ResponseWriter, req *http.Request, p *Re func (p *ReverseProxy) WrappedServeHTTP(rw http.ResponseWriter, req *http.Request, withCache bool) *http.Response { // 1. Check if timeouts are set for this endpoint - _, timeout := p.CheckHardTimeoutEnforced(p.TykAPISpec, req) - transport := httpTransport(timeout, rw, req, p) + if p.TykAPISpec.HTTPTransport == nil { + _, timeout := p.CheckHardTimeoutEnforced(p.TykAPISpec, req) + p.TykAPISpec.HTTPTransport = httpTransport(timeout, rw, req, p) + } ctx := req.Context() if cn, ok := rw.(http.CloseNotifier); ok { @@ -525,14 +527,14 @@ func (p *ReverseProxy) WrappedServeHTTP(rw http.ResponseWriter, req *http.Reques p.ErrorHandler.HandleError(rw, logreq, "Service temporarily unnavailable.", 503) return nil } - res, err = transport.RoundTrip(outreq) + res, err = p.TykAPISpec.HTTPTransport.RoundTrip(outreq) if err != nil || res.StatusCode == 500 { breakerConf.CB.Fail() } else { breakerConf.CB.Success() } } else { - res, err = transport.RoundTrip(outreq) + res, err = p.TykAPISpec.HTTPTransport.RoundTrip(outreq) } if err != nil {