Removing timeout on shutdown (#19956)

This commit is contained in:
Sveinn 2024-06-19 11:42:47 -07:00 committed by GitHub
parent 7a4b250c8b
commit bce93b5cfa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 11 additions and 72 deletions

View File

@ -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)

View File

@ -163,7 +163,6 @@ type serverCtxt struct {
MemLimit uint64
UserTimeout time.Duration
ShutdownTimeout time.Duration
IdleTimeout time.Duration
ReadHeaderTimeout time.Duration
MaxIdleConnsPerHost int

View File

@ -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).

View File

@ -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

View File

@ -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)
}