diff --git a/cmd/gateway-main.go b/cmd/gateway-main.go index d969a88d9..27ca23b2a 100644 --- a/cmd/gateway-main.go +++ b/cmd/gateway-main.go @@ -260,8 +260,16 @@ func StartGateway(ctx *cli.Context, gw Gateway) { getCert = globalTLSCerts.GetCertificate } - httpServer := xhttp.NewServer([]string{globalMinioAddr}, - criticalErrorHandler{corsHandler(router)}, getCert) + listeners := ctx.Int("listeners") + if listeners == 0 { + listeners = 1 + } + addrs := make([]string, 0, listeners) + for i := 0; i < listeners; i++ { + addrs = append(addrs, globalMinioAddr) + } + + httpServer := xhttp.NewServer(addrs, criticalErrorHandler{corsHandler(router)}, getCert) httpServer.BaseContext = func(listener net.Listener) context.Context { return GlobalContext } diff --git a/cmd/server-main.go b/cmd/server-main.go index b31695060..0aade162e 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -55,6 +55,11 @@ var ServerFlags = []cli.Flag{ Value: ":" + GlobalMinioDefaultPort, Usage: "bind to a specific ADDRESS:PORT, ADDRESS can be an IP or hostname", }, + cli.IntFlag{ + Name: "listeners", + Value: 1, + Usage: "bind N number of listeners per ADDRESS:PORT", + }, cli.StringFlag{ Name: "console-address", Usage: "bind to a specific ADDRESS:PORT for embedded Console UI, ADDRESS can be an IP or hostname", @@ -497,8 +502,16 @@ func serverMain(ctx *cli.Context) { getCert = globalTLSCerts.GetCertificate } - httpServer := xhttp.NewServer([]string{globalMinioAddr}, - criticalErrorHandler{corsHandler(handler)}, getCert) + listeners := ctx.Int("listeners") + if listeners == 0 { + listeners = 1 + } + addrs := make([]string, 0, listeners) + for i := 0; i < listeners; i++ { + addrs = append(addrs, globalMinioAddr) + } + + httpServer := xhttp.NewServer(addrs, criticalErrorHandler{corsHandler(handler)}, getCert) httpServer.BaseContext = func(listener net.Listener) context.Context { return GlobalContext } diff --git a/internal/http/listener.go b/internal/http/listener.go index 23d0b14f5..56c95d7bb 100644 --- a/internal/http/listener.go +++ b/internal/http/listener.go @@ -27,6 +27,7 @@ import ( type acceptResult struct { conn net.Conn err error + lidx int } // httpListener - HTTP listener capable of handling multiple server addresses. @@ -47,38 +48,24 @@ func (listener *httpListener) start() { // Successfully written to acceptCh return true case <-listener.ctx.Done(): - // As stop signal is received, close accepted connection. - if result.conn != nil { - result.conn.Close() - } return false } } - // Closure to handle single connection. - handleConn := func(tcpConn *net.TCPConn) { - tcpConn.SetKeepAlive(true) - send(acceptResult{tcpConn, nil}) - } - // Closure to handle TCPListener until done channel is closed. - handleListener := func(tcpListener *net.TCPListener) { + handleListener := func(idx int, tcpListener *net.TCPListener) { for { tcpConn, err := tcpListener.AcceptTCP() - if err != nil { - // Returns when send fails. - if !send(acceptResult{nil, err}) { - return - } - } else { - go handleConn(tcpConn) + if tcpConn != nil { + tcpConn.SetKeepAlive(true) } + send(acceptResult{tcpConn, err, idx}) } } // Start separate goroutine for each TCP listener to handle connection. - for _, tcpListener := range listener.tcpListeners { - go handleListener(tcpListener) + for idx, tcpListener := range listener.tcpListeners { + go handleListener(idx, tcpListener) } }