X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/e56ae6aad06c37d5512537047871d7363dd97620..75c5b123e0b4cbfebed9b15364a97c2209f94740:/services/keepproxy/keepproxy.go diff --git a/services/keepproxy/keepproxy.go b/services/keepproxy/keepproxy.go index 65f7a42cd9..44ecae451f 100644 --- a/services/keepproxy/keepproxy.go +++ b/services/keepproxy/keepproxy.go @@ -133,7 +133,6 @@ func main() { if cfg.DefaultReplicas > 0 { kc.Want_replicas = cfg.DefaultReplicas } - kc.Client.(*http.Client).Timeout = time.Duration(cfg.Timeout) go kc.RefreshServices(5*time.Minute, 3*time.Second) listener, err = net.Listen("tcp", cfg.Listen) @@ -157,7 +156,7 @@ func main() { signal.Notify(term, syscall.SIGINT) // Start serving requests. - router = MakeRESTRouter(!cfg.DisableGet, !cfg.DisablePut, kc) + router = MakeRESTRouter(!cfg.DisableGet, !cfg.DisablePut, kc, time.Duration(cfg.Timeout)) http.Serve(listener, router) log.Println("shutting down") @@ -241,21 +240,41 @@ type proxyHandler struct { http.Handler *keepclient.KeepClient *ApiTokenCache + timeout time.Duration + transport *http.Transport } // MakeRESTRouter returns an http.Handler that passes GET and PUT // requests to the appropriate handlers. -func MakeRESTRouter(enable_get bool, enable_put bool, kc *keepclient.KeepClient) http.Handler { +func MakeRESTRouter(enable_get bool, enable_put bool, kc *keepclient.KeepClient, timeout time.Duration) http.Handler { rest := mux.NewRouter() + + transport := *(http.DefaultTransport.(*http.Transport)) + transport.DialContext = (&net.Dialer{ + Timeout: keepclient.DefaultConnectTimeout, + KeepAlive: keepclient.DefaultKeepAlive, + DualStack: true, + }).DialContext + transport.TLSClientConfig = arvadosclient.MakeTLSConfig(kc.Arvados.ApiInsecure) + transport.TLSHandshakeTimeout = keepclient.DefaultTLSHandshakeTimeout + h := &proxyHandler{ Handler: rest, KeepClient: kc, + timeout: timeout, + transport: &transport, ApiTokenCache: &ApiTokenCache{ tokens: make(map[string]int64), expireTime: 300, }, } + go func(t *http.Transport) { + for range time.NewTicker(5 * time.Minute).C { + t.CloseIdleConnections() + } + }(h.transport) + if enable_get { rest.HandleFunc(`/{locator:[0-9a-f]{32}\+.*}`, h.Get).Methods("GET", "HEAD") rest.HandleFunc(`/{locator:[0-9a-f]{32}}`, h.Get).Methods("GET", "HEAD") @@ -335,12 +354,11 @@ func (h *proxyHandler) Get(resp http.ResponseWriter, req *http.Request) { } }() - kc := *h.KeepClient - kc.Client = &proxyClient{client: kc.Client, proto: req.Proto} + kc := h.makeKeepClient(req) var pass bool var tok string - if pass, tok = CheckAuthorizationHeader(&kc, h.ApiTokenCache, req); !pass { + if pass, tok = CheckAuthorizationHeader(kc, h.ApiTokenCache, req); !pass { status, err = http.StatusForbidden, BadAuthorizationHeader return } @@ -407,8 +425,7 @@ func (h *proxyHandler) Put(resp http.ResponseWriter, req *http.Request) { SetCorsHeaders(resp) resp.Header().Set("Via", "HTTP/1.1 "+viaAlias) - kc := *h.KeepClient - kc.Client = &proxyClient{client: kc.Client, proto: req.Proto} + kc := h.makeKeepClient(req) var err error var expectLength int64 @@ -446,7 +463,7 @@ func (h *proxyHandler) Put(resp http.ResponseWriter, req *http.Request) { var pass bool var tok string - if pass, tok = CheckAuthorizationHeader(&kc, h.ApiTokenCache, req); !pass { + if pass, tok = CheckAuthorizationHeader(kc, h.ApiTokenCache, req); !pass { err = BadAuthorizationHeader status = http.StatusForbidden return @@ -527,9 +544,8 @@ func (h *proxyHandler) Index(resp http.ResponseWriter, req *http.Request) { } }() - kc := *h.KeepClient - - ok, token := CheckAuthorizationHeader(&kc, h.ApiTokenCache, req) + kc := h.makeKeepClient(req) + ok, token := CheckAuthorizationHeader(kc, h.ApiTokenCache, req) if !ok { status, err = http.StatusForbidden, BadAuthorizationHeader return @@ -566,3 +582,15 @@ func (h *proxyHandler) Index(resp http.ResponseWriter, req *http.Request) { status = http.StatusOK resp.Write([]byte("\n")) } + +func (h *proxyHandler) makeKeepClient(req *http.Request) *keepclient.KeepClient { + kc := *h.KeepClient + kc.HTTPClient = &proxyClient{ + client: &http.Client{ + Timeout: h.timeout, + Transport: h.transport, + }, + proto: req.Proto, + } + return &kc +}