diff --git a/internal/pool/pool.go b/internal/pool/pool.go index 986c05d0a..7cf96fb6b 100644 --- a/internal/pool/pool.go +++ b/internal/pool/pool.go @@ -62,10 +62,10 @@ type Options struct { PoolFIFO bool PoolSize int + PoolSizeStrict bool PoolTimeout time.Duration MinIdleConns int MaxIdleConns int - MaxActiveConns int ConnMaxIdleTime time.Duration ConnMaxLifetime time.Duration } @@ -164,13 +164,12 @@ func (p *ConnPool) NewConn(ctx context.Context) (*Conn, error) { } func (p *ConnPool) newConn(ctx context.Context, pooled bool) (*Conn, error) { - if p.closed() { - return nil, ErrClosed - } - - if p.cfg.MaxActiveConns > 0 && p.poolSize >= p.cfg.MaxActiveConns { + p.connsMu.Lock() + if p.cfg.PoolSizeStrict && len(p.conns) >= p.cfg.PoolSize { + p.connsMu.Unlock() return nil, ErrPoolExhausted } + p.connsMu.Unlock() cn, err := p.dialConn(ctx, pooled) if err != nil { @@ -180,6 +179,12 @@ func (p *ConnPool) newConn(ctx context.Context, pooled bool) (*Conn, error) { p.connsMu.Lock() defer p.connsMu.Unlock() + // It is not allowed to add new connections to the closed connection pool. + if p.closed() { + _ = cn.Close() + return nil, ErrClosed + } + p.conns = append(p.conns, cn) if pooled { // If pool is full remove the cn on next Put. diff --git a/options.go b/options.go index 449a92521..389745cb0 100644 --- a/options.go +++ b/options.go @@ -100,9 +100,12 @@ type Options struct { PoolFIFO bool // Base number of socket connections. // Default is 10 connections per every available CPU as reported by runtime.GOMAXPROCS. - // If there is not enough connections in the pool, new connections will be allocated in excess of PoolSize, - // you can limit it through MaxActiveConns + // If there are not enough connections in the pool, new connections will be allocated beyond the PoolSize, + // which can flood the server with connections under heavy load. + // To enable standard pool behavior with overflow checking, use the PoolSizeStrict parameter PoolSize int + // Enabling classic pool mode, when it is guaranteed that no more connections will open to the server than specified in PoolSize + PoolSizeStrict bool // Amount of time client waits for connection if all connections // are busy before returning an error. // Default is ReadTimeout + 1 second. @@ -114,9 +117,6 @@ type Options struct { // Maximum number of idle connections. // Default is 0. the idle connections are not closed by default. MaxIdleConns int - // Maximum number of connections allocated by the pool at a given time. - // When zero, there is no limit on the number of connections in the pool. - MaxActiveConns int // ConnMaxIdleTime is the maximum amount of time a connection may be idle. // Should be less than server's timeout. // @@ -458,10 +458,10 @@ func setupConnParams(u *url.URL, o *Options) (*Options, error) { o.WriteTimeout = q.duration("write_timeout") o.PoolFIFO = q.bool("pool_fifo") o.PoolSize = q.int("pool_size") + o.PoolSizeStrict = q.bool("pool_size_strict") o.PoolTimeout = q.duration("pool_timeout") o.MinIdleConns = q.int("min_idle_conns") o.MaxIdleConns = q.int("max_idle_conns") - o.MaxActiveConns = q.int("max_active_conns") if q.has("conn_max_idle_time") { o.ConnMaxIdleTime = q.duration("conn_max_idle_time") } else { @@ -505,10 +505,10 @@ func newConnPool( }, PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, + PoolSizeStrict: opt.PoolSizeStrict, PoolTimeout: opt.PoolTimeout, MinIdleConns: opt.MinIdleConns, MaxIdleConns: opt.MaxIdleConns, - MaxActiveConns: opt.MaxActiveConns, ConnMaxIdleTime: opt.ConnMaxIdleTime, ConnMaxLifetime: opt.ConnMaxLifetime, }) diff --git a/osscluster.go b/osscluster.go index 93e0eef1e..3b893cf5d 100644 --- a/osscluster.go +++ b/osscluster.go @@ -76,11 +76,11 @@ type ClusterOptions struct { ContextTimeoutEnabled bool PoolFIFO bool - PoolSize int // applies per cluster node and not for the whole cluster + PoolSize int // applies per cluster node and not for the whole cluster + PoolSizeStrict bool // applies per cluster node and not for the whole cluster PoolTimeout time.Duration MinIdleConns int MaxIdleConns int - MaxActiveConns int // applies per cluster node and not for the whole cluster ConnMaxIdleTime time.Duration ConnMaxLifetime time.Duration @@ -233,9 +233,9 @@ func setupClusterQueryParams(u *url.URL, o *ClusterOptions) (*ClusterOptions, er o.WriteTimeout = q.duration("write_timeout") o.PoolFIFO = q.bool("pool_fifo") o.PoolSize = q.int("pool_size") + o.PoolSizeStrict = q.bool("pool_size_strict") o.MinIdleConns = q.int("min_idle_conns") o.MaxIdleConns = q.int("max_idle_conns") - o.MaxActiveConns = q.int("max_active_conns") o.PoolTimeout = q.duration("pool_timeout") o.ConnMaxLifetime = q.duration("conn_max_lifetime") o.ConnMaxIdleTime = q.duration("conn_max_idle_time") @@ -284,10 +284,10 @@ func (opt *ClusterOptions) clientOptions() *Options { PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, + PoolSizeStrict: opt.PoolSizeStrict, PoolTimeout: opt.PoolTimeout, MinIdleConns: opt.MinIdleConns, MaxIdleConns: opt.MaxIdleConns, - MaxActiveConns: opt.MaxActiveConns, ConnMaxIdleTime: opt.ConnMaxIdleTime, ConnMaxLifetime: opt.ConnMaxLifetime, DisableIndentity: opt.DisableIndentity, diff --git a/ring.go b/ring.go index 367a542e9..31282f20c 100644 --- a/ring.go +++ b/ring.go @@ -88,10 +88,10 @@ type RingOptions struct { PoolFIFO bool PoolSize int + PoolSizeStrict bool PoolTimeout time.Duration MinIdleConns int MaxIdleConns int - MaxActiveConns int ConnMaxIdleTime time.Duration ConnMaxLifetime time.Duration @@ -155,10 +155,10 @@ func (opt *RingOptions) clientOptions() *Options { PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, + PoolSizeStrict: opt.PoolSizeStrict, PoolTimeout: opt.PoolTimeout, MinIdleConns: opt.MinIdleConns, MaxIdleConns: opt.MaxIdleConns, - MaxActiveConns: opt.MaxActiveConns, ConnMaxIdleTime: opt.ConnMaxIdleTime, ConnMaxLifetime: opt.ConnMaxLifetime, diff --git a/sentinel.go b/sentinel.go index 31ea3c77a..b2500132d 100644 --- a/sentinel.go +++ b/sentinel.go @@ -71,10 +71,10 @@ type FailoverOptions struct { PoolFIFO bool PoolSize int + PoolSizeStrict bool PoolTimeout time.Duration MinIdleConns int MaxIdleConns int - MaxActiveConns int ConnMaxIdleTime time.Duration ConnMaxLifetime time.Duration @@ -107,10 +107,10 @@ func (opt *FailoverOptions) clientOptions() *Options { PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, + PoolSizeStrict: opt.PoolSizeStrict, PoolTimeout: opt.PoolTimeout, MinIdleConns: opt.MinIdleConns, MaxIdleConns: opt.MaxIdleConns, - MaxActiveConns: opt.MaxActiveConns, ConnMaxIdleTime: opt.ConnMaxIdleTime, ConnMaxLifetime: opt.ConnMaxLifetime, @@ -143,10 +143,10 @@ func (opt *FailoverOptions) sentinelOptions(addr string) *Options { PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, + PoolSizeStrict: opt.PoolSizeStrict, PoolTimeout: opt.PoolTimeout, MinIdleConns: opt.MinIdleConns, MaxIdleConns: opt.MaxIdleConns, - MaxActiveConns: opt.MaxActiveConns, ConnMaxIdleTime: opt.ConnMaxIdleTime, ConnMaxLifetime: opt.ConnMaxLifetime, @@ -180,10 +180,10 @@ func (opt *FailoverOptions) clusterOptions() *ClusterOptions { PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, + PoolSizeStrict: opt.PoolSizeStrict, PoolTimeout: opt.PoolTimeout, MinIdleConns: opt.MinIdleConns, MaxIdleConns: opt.MaxIdleConns, - MaxActiveConns: opt.MaxActiveConns, ConnMaxIdleTime: opt.ConnMaxIdleTime, ConnMaxLifetime: opt.ConnMaxLifetime, diff --git a/universal.go b/universal.go index 1e48d7b90..c13bb55e9 100644 --- a/universal.go +++ b/universal.go @@ -45,10 +45,10 @@ type UniversalOptions struct { PoolFIFO bool PoolSize int + PoolSizeStrict bool PoolTimeout time.Duration MinIdleConns int MaxIdleConns int - MaxActiveConns int ConnMaxIdleTime time.Duration ConnMaxLifetime time.Duration @@ -102,10 +102,10 @@ func (o *UniversalOptions) Cluster() *ClusterOptions { PoolFIFO: o.PoolFIFO, PoolSize: o.PoolSize, + PoolSizeStrict: o.PoolSizeStrict, PoolTimeout: o.PoolTimeout, MinIdleConns: o.MinIdleConns, MaxIdleConns: o.MaxIdleConns, - MaxActiveConns: o.MaxActiveConns, ConnMaxIdleTime: o.ConnMaxIdleTime, ConnMaxLifetime: o.ConnMaxLifetime, @@ -147,10 +147,10 @@ func (o *UniversalOptions) Failover() *FailoverOptions { PoolFIFO: o.PoolFIFO, PoolSize: o.PoolSize, + PoolSizeStrict: o.PoolSizeStrict, PoolTimeout: o.PoolTimeout, MinIdleConns: o.MinIdleConns, MaxIdleConns: o.MaxIdleConns, - MaxActiveConns: o.MaxActiveConns, ConnMaxIdleTime: o.ConnMaxIdleTime, ConnMaxLifetime: o.ConnMaxLifetime, @@ -189,10 +189,10 @@ func (o *UniversalOptions) Simple() *Options { PoolFIFO: o.PoolFIFO, PoolSize: o.PoolSize, + PoolSizeStrict: o.PoolSizeStrict, PoolTimeout: o.PoolTimeout, MinIdleConns: o.MinIdleConns, MaxIdleConns: o.MaxIdleConns, - MaxActiveConns: o.MaxActiveConns, ConnMaxIdleTime: o.ConnMaxIdleTime, ConnMaxLifetime: o.ConnMaxLifetime,