mirror of
https://github.com/minio/minio.git
synced 2025-04-11 23:12:12 -04:00
add configurable 'shutdown-timeout' for HTTP server (#13771)
fixes #12317
This commit is contained in:
parent
99d87c5ca2
commit
e49c184595
@ -20,7 +20,8 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@ -269,10 +270,13 @@ func StartGateway(ctx *cli.Context, gw Gateway) {
|
|||||||
addrs = append(addrs, globalMinioAddr)
|
addrs = append(addrs, globalMinioAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
httpServer := xhttp.NewServer(addrs, setCriticalErrorHandler(corsHandler(router)), getCert)
|
httpServer := xhttp.NewServer(addrs).
|
||||||
httpServer.BaseContext = func(listener net.Listener) context.Context {
|
UseHandler(setCriticalErrorHandler(corsHandler(router))).
|
||||||
return GlobalContext
|
UseTLSConfig(newTLSConfig(getCert)).
|
||||||
}
|
UseShutdownTimeout(ctx.Duration("shutdown-timeout")).
|
||||||
|
UseBaseContext(GlobalContext).
|
||||||
|
UseCustomLogger(log.New(ioutil.Discard, "", 0)) // Turn-off random logging by Go stdlib
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
globalHTTPServerErrorCh <- httpServer.Start(GlobalContext)
|
globalHTTPServerErrorCh <- httpServer.Start(GlobalContext)
|
||||||
}()
|
}()
|
||||||
|
@ -23,9 +23,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
@ -64,6 +64,12 @@ var ServerFlags = []cli.Flag{
|
|||||||
Name: "console-address",
|
Name: "console-address",
|
||||||
Usage: "bind to a specific ADDRESS:PORT for embedded Console UI, ADDRESS can be an IP or hostname",
|
Usage: "bind to a specific ADDRESS:PORT for embedded Console UI, ADDRESS can be an IP or hostname",
|
||||||
},
|
},
|
||||||
|
cli.DurationFlag{
|
||||||
|
Name: "shutdown-timeout",
|
||||||
|
Value: xhttp.DefaultShutdownTimeout,
|
||||||
|
Usage: "shutdown timeout to gracefully shutdown server",
|
||||||
|
Hidden: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var serverCmd = cli.Command{
|
var serverCmd = cli.Command{
|
||||||
@ -412,12 +418,6 @@ func initConfigSubsystem(ctx context.Context, newObject ObjectLayer) ([]BucketIn
|
|||||||
return buckets, nil
|
return buckets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type nullWriter struct{}
|
|
||||||
|
|
||||||
func (lw nullWriter) Write(b []byte) (int, error) {
|
|
||||||
return len(b), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// serverMain handler called for 'minio server' command.
|
// serverMain handler called for 'minio server' command.
|
||||||
func serverMain(ctx *cli.Context) {
|
func serverMain(ctx *cli.Context) {
|
||||||
signal.Notify(globalOSSignalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
|
signal.Notify(globalOSSignalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
|
||||||
@ -492,12 +492,13 @@ func serverMain(ctx *cli.Context) {
|
|||||||
addrs = append(addrs, globalMinioAddr)
|
addrs = append(addrs, globalMinioAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
httpServer := xhttp.NewServer(addrs, setCriticalErrorHandler(corsHandler(handler)), getCert)
|
httpServer := xhttp.NewServer(addrs).
|
||||||
httpServer.BaseContext = func(listener net.Listener) context.Context {
|
UseHandler(setCriticalErrorHandler(corsHandler(handler))).
|
||||||
return GlobalContext
|
UseTLSConfig(newTLSConfig(getCert)).
|
||||||
}
|
UseShutdownTimeout(ctx.Duration("shutdown-timeout")).
|
||||||
// Turn-off random logging by Go internally
|
UseBaseContext(GlobalContext).
|
||||||
httpServer.ErrorLog = log.New(&nullWriter{}, "", 0)
|
UseCustomLogger(log.New(ioutil.Discard, "", 0)) // Turn-off random logging by Go stdlib
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
globalHTTPServerErrorCh <- httpServer.Start(GlobalContext)
|
globalHTTPServerErrorCh <- httpServer.Start(GlobalContext)
|
||||||
}()
|
}()
|
||||||
|
36
cmd/utils.go
36
cmd/utils.go
@ -46,12 +46,17 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/minio/madmin-go"
|
"github.com/minio/madmin-go"
|
||||||
miniogopolicy "github.com/minio/minio-go/v7/pkg/policy"
|
miniogopolicy "github.com/minio/minio-go/v7/pkg/policy"
|
||||||
|
"github.com/minio/minio/internal/config"
|
||||||
|
"github.com/minio/minio/internal/config/api"
|
||||||
|
xtls "github.com/minio/minio/internal/config/identity/tls"
|
||||||
|
"github.com/minio/minio/internal/fips"
|
||||||
"github.com/minio/minio/internal/handlers"
|
"github.com/minio/minio/internal/handlers"
|
||||||
xhttp "github.com/minio/minio/internal/http"
|
xhttp "github.com/minio/minio/internal/http"
|
||||||
"github.com/minio/minio/internal/logger"
|
"github.com/minio/minio/internal/logger"
|
||||||
"github.com/minio/minio/internal/logger/message/audit"
|
"github.com/minio/minio/internal/logger/message/audit"
|
||||||
"github.com/minio/minio/internal/rest"
|
"github.com/minio/minio/internal/rest"
|
||||||
"github.com/minio/pkg/certs"
|
"github.com/minio/pkg/certs"
|
||||||
|
"github.com/minio/pkg/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -1097,3 +1102,34 @@ func speedTest(ctx context.Context, opts speedTestOpts) chan madmin.SpeedTestRes
|
|||||||
}()
|
}()
|
||||||
return ch
|
return ch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newTLSConfig(getCert certs.GetCertificateFunc) *tls.Config {
|
||||||
|
if getCert == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
PreferServerCipherSuites: true,
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
|
NextProtos: []string{"http/1.1", "h2"},
|
||||||
|
GetCertificate: getCert,
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsClientIdentity := env.Get(xtls.EnvIdentityTLSEnabled, "") == config.EnableOn
|
||||||
|
if tlsClientIdentity {
|
||||||
|
tlsConfig.ClientAuth = tls.RequestClientCert
|
||||||
|
}
|
||||||
|
|
||||||
|
secureCiphers := env.Get(api.EnvAPISecureCiphers, config.EnableOn) == config.EnableOn
|
||||||
|
if secureCiphers || fips.Enabled {
|
||||||
|
// Hardened ciphers
|
||||||
|
tlsConfig.CipherSuites = fips.CipherSuitesTLS()
|
||||||
|
tlsConfig.CurvePreferences = fips.EllipticCurvesTLS()
|
||||||
|
} else {
|
||||||
|
// Default ciphers while excluding those with security issues
|
||||||
|
for _, cipher := range tls.CipherSuites() {
|
||||||
|
tlsConfig.CipherSuites = append(tlsConfig.CipherSuites, cipher.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tlsConfig
|
||||||
|
}
|
||||||
|
@ -22,6 +22,8 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
"sync"
|
"sync"
|
||||||
@ -29,19 +31,12 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
humanize "github.com/dustin/go-humanize"
|
humanize "github.com/dustin/go-humanize"
|
||||||
|
|
||||||
"github.com/minio/minio/internal/config"
|
|
||||||
"github.com/minio/minio/internal/config/api"
|
|
||||||
xtls "github.com/minio/minio/internal/config/identity/tls"
|
|
||||||
"github.com/minio/minio/internal/fips"
|
|
||||||
"github.com/minio/pkg/certs"
|
|
||||||
"github.com/minio/pkg/env"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
serverShutdownPoll = 500 * time.Millisecond
|
serverShutdownPoll = 500 * time.Millisecond
|
||||||
|
|
||||||
// DefaultShutdownTimeout - default shutdown timeout used for graceful http server shutdown.
|
// DefaultShutdownTimeout - default shutdown timeout to gracefully shutdown server.
|
||||||
DefaultShutdownTimeout = 5 * time.Second
|
DefaultShutdownTimeout = 5 * time.Second
|
||||||
|
|
||||||
// DefaultMaxHeaderBytes - default maximum HTTP header size in bytes.
|
// DefaultMaxHeaderBytes - default maximum HTTP header size in bytes.
|
||||||
@ -160,42 +155,44 @@ func (srv *Server) Shutdown() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UseShutdownTimeout configure server shutdown timeout
|
||||||
|
func (srv *Server) UseShutdownTimeout(d time.Duration) *Server {
|
||||||
|
srv.ShutdownTimeout = d
|
||||||
|
return srv
|
||||||
|
}
|
||||||
|
|
||||||
|
// UseHandler configure final handler for this HTTP *Server
|
||||||
|
func (srv *Server) UseHandler(h http.Handler) *Server {
|
||||||
|
srv.Handler = h
|
||||||
|
return srv
|
||||||
|
}
|
||||||
|
|
||||||
|
// UseTLSConfig pass configured TLSConfig for this HTTP *Server
|
||||||
|
func (srv *Server) UseTLSConfig(cfg *tls.Config) *Server {
|
||||||
|
srv.TLSConfig = cfg
|
||||||
|
return srv
|
||||||
|
}
|
||||||
|
|
||||||
|
// UseBaseContext use custom base context for this HTTP *Server
|
||||||
|
func (srv *Server) UseBaseContext(ctx context.Context) *Server {
|
||||||
|
srv.BaseContext = func(listener net.Listener) context.Context {
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
return srv
|
||||||
|
}
|
||||||
|
|
||||||
|
// UseCustomLogger use customized logger for this HTTP *Server
|
||||||
|
func (srv *Server) UseCustomLogger(l *log.Logger) *Server {
|
||||||
|
srv.ErrorLog = l
|
||||||
|
return srv
|
||||||
|
}
|
||||||
|
|
||||||
// NewServer - creates new HTTP server using given arguments.
|
// NewServer - creates new HTTP server using given arguments.
|
||||||
func NewServer(addrs []string, handler http.Handler, getCert certs.GetCertificateFunc) *Server {
|
func NewServer(addrs []string) *Server {
|
||||||
secureCiphers := env.Get(api.EnvAPISecureCiphers, config.EnableOn) == config.EnableOn
|
|
||||||
var tlsConfig *tls.Config
|
|
||||||
if getCert != nil {
|
|
||||||
tlsConfig = &tls.Config{
|
|
||||||
PreferServerCipherSuites: true,
|
|
||||||
MinVersion: tls.VersionTLS12,
|
|
||||||
NextProtos: []string{"http/1.1", "h2"},
|
|
||||||
GetCertificate: getCert,
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsClientIdentity := env.Get(xtls.EnvIdentityTLSEnabled, "") == config.EnableOn
|
|
||||||
if tlsClientIdentity {
|
|
||||||
tlsConfig.ClientAuth = tls.RequestClientCert
|
|
||||||
}
|
|
||||||
|
|
||||||
if secureCiphers || fips.Enabled {
|
|
||||||
// Hardened ciphers
|
|
||||||
tlsConfig.CipherSuites = fips.CipherSuitesTLS()
|
|
||||||
tlsConfig.CurvePreferences = fips.EllipticCurvesTLS()
|
|
||||||
} else {
|
|
||||||
// Default ciphers while excluding those with security issues
|
|
||||||
for _, cipher := range tls.CipherSuites() {
|
|
||||||
tlsConfig.CipherSuites = append(tlsConfig.CipherSuites, cipher.ID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
httpServer := &Server{
|
httpServer := &Server{
|
||||||
Addrs: addrs,
|
Addrs: addrs,
|
||||||
ShutdownTimeout: DefaultShutdownTimeout,
|
|
||||||
}
|
}
|
||||||
httpServer.Handler = handler
|
// This is not configurable for now.
|
||||||
httpServer.TLSConfig = tlsConfig
|
|
||||||
httpServer.MaxHeaderBytes = DefaultMaxHeaderBytes
|
httpServer.MaxHeaderBytes = DefaultMaxHeaderBytes
|
||||||
|
|
||||||
return httpServer
|
return httpServer
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -46,7 +47,15 @@ func TestNewServer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, testCase := range testCases {
|
for i, testCase := range testCases {
|
||||||
server := NewServer(testCase.addrs, testCase.handler, testCase.certFn)
|
server := NewServer(testCase.addrs).
|
||||||
|
UseHandler(testCase.handler).
|
||||||
|
UseShutdownTimeout(DefaultShutdownTimeout)
|
||||||
|
if testCase.certFn != nil {
|
||||||
|
server = server.UseTLSConfig(&tls.Config{
|
||||||
|
PreferServerCipherSuites: true,
|
||||||
|
GetCertificate: testCase.certFn,
|
||||||
|
})
|
||||||
|
}
|
||||||
if server == nil {
|
if server == nil {
|
||||||
t.Fatalf("Case %v: server: expected: <non-nil>, got: <nil>", (i + 1))
|
t.Fatalf("Case %v: server: expected: <non-nil>, got: <nil>", (i + 1))
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user