mirror of
https://github.com/kataras/iris.git
synced 2026-01-06 11:37:06 +00:00
Option for Socket Sharding as requested at #1544
Former-commit-id: 0384baf593012377a94344d647ca41121294285a
This commit is contained in:
@@ -13,9 +13,9 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/acme/autocert"
|
||||
|
||||
"github.com/kataras/iris/v12/core/netutil"
|
||||
|
||||
"golang.org/x/crypto/acme/autocert"
|
||||
)
|
||||
|
||||
// Configurator provides an easy way to modify
|
||||
@@ -48,6 +48,9 @@ type Supervisor struct {
|
||||
// Defaults to empty.
|
||||
IgnoredErrors []string
|
||||
onErr []func(error)
|
||||
|
||||
// See `iris.Configuration.SocketSharding`.
|
||||
SocketSharding bool
|
||||
}
|
||||
|
||||
// New returns a new host supervisor
|
||||
@@ -124,8 +127,8 @@ func (su *Supervisor) newListener() (net.Listener, error) {
|
||||
// restarts we may want for the server.
|
||||
//
|
||||
// User still be able to call .Serve instead.
|
||||
// l, err := netutil.TCPKeepAlive(su.Server.Addr)
|
||||
l, err := netutil.TCP(su.Server.Addr)
|
||||
// l, err := netutil.TCPKeepAlive(su.Server.Addr, su.SocketReuse)
|
||||
l, err := netutil.TCP(su.Server.Addr, su.SocketSharding)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -367,7 +370,13 @@ func (su *Supervisor) runTLS(getCertificate func(*tls.ClientHelloInfo) (*tls.Cer
|
||||
defer cancel()
|
||||
http1RedirectServer.Shutdown(ctx)
|
||||
})
|
||||
go http1RedirectServer.ListenAndServe()
|
||||
|
||||
ln, err := netutil.TCP(":http", su.SocketSharding)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go http1RedirectServer.Serve(ln)
|
||||
}
|
||||
|
||||
if su.Server.TLSConfig == nil {
|
||||
@@ -401,7 +410,12 @@ func (su *Supervisor) runTLS(getCertificate func(*tls.ClientHelloInfo) (*tls.Cer
|
||||
}
|
||||
}
|
||||
|
||||
return su.supervise(func() error { return su.Server.ListenAndServeTLS("", "") })
|
||||
ln, err := netutil.TCP(su.Server.Addr, su.SocketSharding)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return su.supervise(func() error { return su.Server.ServeTLS(ln, "", "") })
|
||||
}
|
||||
|
||||
// RegisterOnShutdown registers a function to call on Shutdown.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -38,16 +39,17 @@ func (l tcpKeepAliveListener) Accept() (net.Conn, error) {
|
||||
}
|
||||
|
||||
// TCP returns a new tcp(ipv6 if supported by network) and an error on failure.
|
||||
func TCP(addr string) (net.Listener, error) {
|
||||
l, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func TCP(addr string, reuse bool) (net.Listener, error) {
|
||||
var cfg net.ListenConfig
|
||||
if reuse {
|
||||
cfg.Control = control
|
||||
}
|
||||
return l, nil
|
||||
|
||||
return cfg.Listen(context.Background(), "tcp", addr)
|
||||
}
|
||||
|
||||
// TCPKeepAlive returns a new tcp keep alive Listener and an error on failure.
|
||||
func TCPKeepAlive(addr string) (ln net.Listener, err error) {
|
||||
func TCPKeepAlive(addr string, reuse bool) (ln net.Listener, err error) {
|
||||
// if strings.HasPrefix(addr, "127.0.0.1") {
|
||||
// // it's ipv4, use ipv4 tcp listener instead of the default ipv6. Don't.
|
||||
// ln, err = net.Listen("tcp4", addr)
|
||||
@@ -55,7 +57,7 @@ func TCPKeepAlive(addr string) (ln net.Listener, err error) {
|
||||
// ln, err = TCP(addr)
|
||||
// }
|
||||
|
||||
ln, err = TCP(addr)
|
||||
ln, err = TCP(addr, reuse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -110,19 +112,20 @@ func CERT(addr string, cert tls.Certificate) (net.Listener, error) {
|
||||
// LETSENCRYPT returns a new Automatic TLS Listener using letsencrypt.org service
|
||||
// receives three parameters,
|
||||
// the first is the host of the server,
|
||||
// second can be the server name(domain) or empty if skip verification is the expected behavior (not recommended)
|
||||
// and the third is optionally, the cache directory, if you skip it then the cache directory is "./certcache"
|
||||
// second one should declare if the underline tcp listener can be binded more than once,
|
||||
// third can be the server name(domain) or empty if skip verification is the expected behavior (not recommended),
|
||||
// and the forth is optionally, the cache directory, if you skip it then the cache directory is "./certcache"
|
||||
// if you want to disable cache directory then simple give it a value of empty string ""
|
||||
//
|
||||
// does NOT supports localhost domains for testing.
|
||||
//
|
||||
// this is the recommended function to use when you're ready for production state.
|
||||
func LETSENCRYPT(addr string, serverName string, cacheDirOptional ...string) (net.Listener, error) {
|
||||
func LETSENCRYPT(addr string, reuse bool, serverName string, cacheDirOptional ...string) (net.Listener, error) {
|
||||
if portIdx := strings.IndexByte(addr, ':'); portIdx == -1 {
|
||||
addr += ":443"
|
||||
}
|
||||
|
||||
l, err := TCP(addr)
|
||||
l, err := TCP(addr, reuse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
25
core/netutil/tcp_soreuse_control_unix.go
Normal file
25
core/netutil/tcp_soreuse_control_unix.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// +build !windows,!wasm
|
||||
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func control(network, address string, c syscall.RawConn) (err error) {
|
||||
c.Control(func(fd uintptr) {
|
||||
err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
9
core/netutil/tcp_soreuse_control_wasm.go
Normal file
9
core/netutil/tcp_soreuse_control_wasm.go
Normal file
@@ -0,0 +1,9 @@
|
||||
// +build wasm
|
||||
|
||||
package netutil
|
||||
|
||||
import "syscall"
|
||||
|
||||
func control(network, address string, c syscall.RawConn) error {
|
||||
return nil
|
||||
}
|
||||
13
core/netutil/tcp_soreuse_control_windows.go
Normal file
13
core/netutil/tcp_soreuse_control_windows.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func control(network, address string, c syscall.RawConn) (err error) {
|
||||
return c.Control(func(fd uintptr) {
|
||||
err = windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_REUSEADDR, 1)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user