diff --git a/cmd/common-main.go b/cmd/common-main.go index 263e4fb3a..b739f7ef5 100644 --- a/cmd/common-main.go +++ b/cmd/common-main.go @@ -433,7 +433,6 @@ func buildServerCtxt(ctx *cli.Context, ctxt *serverCtxt) (err error) { ctxt.RecvBufSize = ctx.Int("recv-buf-size") ctxt.IdleTimeout = ctx.Duration("idle-timeout") ctxt.UserTimeout = ctx.Duration("conn-user-timeout") - ctxt.ShutdownTimeout = ctx.Duration("shutdown-timeout") if conf := ctx.String("config"); len(conf) > 0 { err = mergeServerCtxtFromConfigFile(conf, ctxt) diff --git a/cmd/globals.go b/cmd/globals.go index 4569c3083..0405c7770 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -163,7 +163,6 @@ type serverCtxt struct { MemLimit uint64 UserTimeout time.Duration - ShutdownTimeout time.Duration IdleTimeout time.Duration ReadHeaderTimeout time.Duration MaxIdleConnsPerHost int diff --git a/cmd/server-main.go b/cmd/server-main.go index 024992d12..9073e672e 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -84,11 +84,12 @@ var ServerFlags = []cli.Flag{ }, cli.DurationFlag{ Name: "shutdown-timeout", - Value: xhttp.DefaultShutdownTimeout, - Usage: "shutdown timeout to gracefully shutdown server", + Value: time.Second * 30, + Usage: "shutdown timeout to gracefully shutdown server (DEPRECATED)", EnvVar: "MINIO_SHUTDOWN_TIMEOUT", Hidden: true, }, + cli.DurationFlag{ Name: "idle-timeout", Value: xhttp.DefaultIdleTimeout, @@ -866,7 +867,6 @@ func serverMain(ctx *cli.Context) { httpServer := xhttp.NewServer(getServerListenAddrs()). UseHandler(setCriticalErrorHandler(corsHandler(handler))). UseTLSConfig(newTLSConfig(getCert)). - UseShutdownTimeout(globalServerCtxt.ShutdownTimeout). UseIdleTimeout(globalServerCtxt.IdleTimeout). UseReadHeaderTimeout(globalServerCtxt.ReadHeaderTimeout). UseBaseContext(GlobalContext). diff --git a/internal/http/server.go b/internal/http/server.go index 9839f72b0..092d3d40a 100644 --- a/internal/http/server.go +++ b/internal/http/server.go @@ -22,11 +22,8 @@ import ( "crypto/tls" "errors" "log" - "math/rand" "net" "net/http" - "os" - "runtime/pprof" "sync" "sync/atomic" "time" @@ -43,11 +40,6 @@ var ( ) const ( - shutdownPollIntervalMax = 500 * time.Millisecond - - // DefaultShutdownTimeout - default shutdown timeout to gracefully shutdown server. - DefaultShutdownTimeout = 5 * time.Second - // DefaultIdleTimeout for idle inactive connections DefaultIdleTimeout = 30 * time.Second @@ -61,13 +53,12 @@ const ( // Server - extended http.Server supports multiple addresses to serve and enhanced connection handling. type Server struct { http.Server - Addrs []string // addresses on which the server listens for new connection. - TCPOptions TCPOptions // all the configurable TCP conn specific configurable options. - ShutdownTimeout time.Duration // timeout used for graceful server shutdown. - listenerMutex sync.Mutex // to guard 'listener' field. - listener *httpListener // HTTP listener for all 'Addrs' field. - inShutdown uint32 // indicates whether the server is in shutdown or not - requestCount int32 // counter holds no. of request in progress. + Addrs []string // addresses on which the server listens for new connection. + TCPOptions TCPOptions // all the configurable TCP conn specific configurable options. + listenerMutex sync.Mutex // to guard 'listener' field. + listener *httpListener // HTTP listener for all 'Addrs' field. + inShutdown uint32 // indicates whether the server is in shutdown or not + requestCount int32 // counter holds no. of request in progress. } // GetRequestCount - returns number of request in progress. @@ -166,53 +157,8 @@ func (srv *Server) Shutdown() error { return err } - pollIntervalBase := time.Millisecond - nextPollInterval := func() time.Duration { - // Add 10% jitter. - interval := pollIntervalBase + time.Duration(rand.Intn(int(pollIntervalBase/10))) - // Double and clamp for next time. - pollIntervalBase *= 2 - if pollIntervalBase > shutdownPollIntervalMax { - pollIntervalBase = shutdownPollIntervalMax - } - return interval - } - // Wait for opened connection to be closed up to Shutdown timeout. - shutdownTimeout := srv.ShutdownTimeout - shutdownTimer := time.NewTimer(shutdownTimeout) - defer shutdownTimer.Stop() - - timer := time.NewTimer(nextPollInterval()) - defer timer.Stop() - for { - select { - case <-shutdownTimer.C: - if atomic.LoadInt32(&srv.requestCount) <= 0 { - return nil - } - - // Write all running goroutines. - tmp, err := os.CreateTemp("", "minio-goroutines-*.txt") - if err == nil { - _ = pprof.Lookup("goroutine").WriteTo(tmp, 1) - tmp.Close() - return errors.New("timed out. some connections are still active. goroutines written to " + tmp.Name()) - } - return errors.New("timed out. some connections are still active") - case <-timer.C: - if atomic.LoadInt32(&srv.requestCount) <= 0 { - return nil - } - timer.Reset(nextPollInterval()) - } - } -} - -// UseShutdownTimeout configure server shutdown timeout -func (srv *Server) UseShutdownTimeout(d time.Duration) *Server { - srv.ShutdownTimeout = d - return srv + return nil } // UseIdleTimeout configure idle connection timeout diff --git a/internal/http/server_test.go b/internal/http/server_test.go index 3773a0979..27f260aed 100644 --- a/internal/http/server_test.go +++ b/internal/http/server_test.go @@ -48,8 +48,7 @@ func TestNewServer(t *testing.T) { for i, testCase := range testCases { server := NewServer(testCase.addrs). - UseHandler(testCase.handler). - UseShutdownTimeout(DefaultShutdownTimeout) + UseHandler(testCase.handler) if testCase.certFn != nil { server = server.UseTLSConfig(&tls.Config{ PreferServerCipherSuites: true, @@ -72,10 +71,6 @@ func TestNewServer(t *testing.T) { } } - if server.ShutdownTimeout != DefaultShutdownTimeout { - t.Fatalf("Case %v: server.ShutdownTimeout: expected: %v, got: %v", (i + 1), DefaultShutdownTimeout, server.ShutdownTimeout) - } - if server.MaxHeaderBytes != DefaultMaxHeaderBytes { t.Fatalf("Case %v: server.MaxHeaderBytes: expected: %v, got: %v", (i + 1), DefaultMaxHeaderBytes, server.MaxHeaderBytes) }