|
66 | 66 | redisPassword string |
67 | 67 | redisUsername string |
68 | 68 | redisDB int |
69 | | - redisPoolSize int |
| 69 | + |
| 70 | + // Redis Config Options |
| 71 | + redisMaxRetries int |
| 72 | + redisMinRetryBackoffMilliseconds int |
| 73 | + redisMaxRetryBackoffMilliseconds int |
| 74 | + |
| 75 | + redisDialTimeoutSeconds int |
| 76 | + redisReadTimeoutSeconds int |
| 77 | + redisWriteTimeoutSeconds int |
| 78 | + |
| 79 | + redisPoolSize int |
| 80 | + redisPoolSizeLiteral int |
| 81 | + redisPoolTimeoutSeconds int |
| 82 | + |
| 83 | + redisMinIdleConns int |
| 84 | + redisMaxIdleConns int |
| 85 | + redisMaxActiveConns int |
| 86 | + redisConnMaxIdleTimeMinutes int |
| 87 | + redisConnMaxLifetimeMinutes int |
70 | 88 |
|
71 | 89 | // Server Config |
72 | 90 | port int |
@@ -126,7 +144,25 @@ const ( |
126 | 144 | redisPasswordEnv = "REDIS_PASSWORD" |
127 | 145 | redisUsernameEnv = "REDIS_USERNAME" |
128 | 146 | redisDBEnv = "REDIS_DB" |
129 | | - redisPoolSizeEnv = "REDIS_POOL_SIZE" |
| 147 | + |
| 148 | + // Redis Config |
| 149 | + redisMaxRetriesEnv = "REDIS_MAX_RETRIES" |
| 150 | + redisMinRetryBackoffMillisecondsEnv = "REDIS_MIN_RETRY_BACKOFF_MILLIS" |
| 151 | + redisMaxRetryBackoffMillisecondsEnv = "REDIS_MAX_RETRY_BACKOFF_MILLIS" |
| 152 | + |
| 153 | + redisDialTimeoutSecondsEnv = "REDIS_DIAL_TIMEOUT_SECONDS" |
| 154 | + redisReadTimeoutSecondsEnv = "REDIS_READ_TIMEOUT_SECONDS" |
| 155 | + redisWriteTimeoutSecondsEnv = "REDIS_WRITE_TIMEOUT_SECONDS" |
| 156 | + |
| 157 | + redisPoolSizeEnv = "REDIS_POOL_SIZE" |
| 158 | + redisPoolSizeLiteralEnv = "REDIS_POOL_SIZE_LITERAL" |
| 159 | + redisPoolTimeoutSecondsEnv = "REDIS_POOL_TIMEOUT_SECONDS" |
| 160 | + |
| 161 | + redisMinIdleConnsEnv = "REDIS_MIN_IDLE_CONNS" |
| 162 | + redisMaxIdleConnsEnv = "REDIS_MAX_IDLE_CONNS" |
| 163 | + redisMaxActiveConnsEnv = "REDIS_MAX_ACTIVE_CONNS" |
| 164 | + redisConnMaxIdleTimeMinutesEnv = "REDIS_CON_MAX_IDLE_TIME_MINUTES" |
| 165 | + redisConnMaxLifetimeMinutesEnv = "REDIS_CON_MAX_LIFETIME_MINUTES" |
130 | 166 |
|
131 | 167 | // Server Config |
132 | 168 | portEnv = "PORT" |
@@ -170,7 +206,25 @@ const ( |
170 | 206 | redisPasswordFlag = "redis-password" |
171 | 207 | redisUsernameFlag = "redis-username" |
172 | 208 | redisDBFlag = "redis-db" |
173 | | - redisPoolSizeFlag = "redis-pool-size" |
| 209 | + |
| 210 | + // Redis Configuration Options |
| 211 | + redisMaxRetriesFlag = "redis-max-retries" |
| 212 | + redisMinRetryBackoffMillisecondsFlag = "redis-min-retry-backoff-milliseconds" |
| 213 | + redisMaxRetryBackoffMillisecondsFlag = "redis-max-retry-backoff-milliseconds" |
| 214 | + |
| 215 | + redisDialTimeoutSecondsFlag = "redis-dial-timeout-seconds" |
| 216 | + redisReadTimeoutSecondsFlag = "redis-read-timeout-seconds" |
| 217 | + redisWriteTimeoutSecondsFlag = "redis-write-timeout-seconds" |
| 218 | + |
| 219 | + redisPoolSizeFlag = "redis-pool-size" |
| 220 | + redisPoolSizeLiteralFlag = "redis-pool-size-literal" |
| 221 | + redisPoolTimeoutSecondsFlag = "redis-pool-timeout" |
| 222 | + |
| 223 | + redisMinIdleConnsFlag = "redis-min-idle-conns" |
| 224 | + redisMaxIdleConnsFlag = "redis-max-idle-conns" |
| 225 | + redisMaxActiveConnsFlag = "redis-max-active-conns" |
| 226 | + redisConnMaxIdleTimeMinutesFlag = "redis-conn-max-idle-time-minutes" |
| 227 | + redisConnMaxLifetimeMinutesFlag = "redis-conn-max-lifetime-minutes" |
174 | 228 |
|
175 | 229 | // Server Config |
176 | 230 | portFlag = "port" |
@@ -214,7 +268,25 @@ func init() { |
214 | 268 | flag.StringVar(&redisPassword, redisPasswordFlag, "", "Optional. Redis password") |
215 | 269 | flag.StringVar(&redisUsername, redisUsernameFlag, "", "Optional. Redis username") |
216 | 270 | flag.IntVar(&redisDB, redisDBFlag, 0, "Database to be selected after connecting to the server.") |
217 | | - flag.IntVar(&redisPoolSize, redisPoolSizeFlag, 10, "sets the redi connection pool size, to this value multipled by the number of CPU available. E.g if this value is 10 and you've 2 CPU the connection pool size will be 20") |
| 271 | + |
| 272 | + // Redis Configuration Options |
| 273 | + flag.IntVar(&redisMaxRetries, redisMaxRetriesFlag, 3, "Maximum number of retries before giving up. Default is 3 retries.") |
| 274 | + flag.IntVar(&redisMinRetryBackoffMilliseconds, redisMinRetryBackoffMillisecondsFlag, 8, "Minimum backoff between each retry.Default is 8 milliseconds;") |
| 275 | + flag.IntVar(&redisMaxRetryBackoffMilliseconds, redisMaxRetryBackoffMillisecondsFlag, 512, "Maximum backoff between each retry. Default is 512 milliseconds") |
| 276 | + |
| 277 | + flag.IntVar(&redisDialTimeoutSeconds, redisDialTimeoutSecondsFlag, 5, "Dial timeout for establishing new connections. Default is 5 seconds") |
| 278 | + flag.IntVar(&redisReadTimeoutSeconds, redisReadTimeoutSecondsFlag, 3, " Timeout for socket reads. If reached, commands will fail with a timeout instead of blocking. Default is 3 seconds.") |
| 279 | + flag.IntVar(&redisWriteTimeoutSeconds, redisWriteTimeoutSecondsFlag, 3, "Timeout for socket writes. If reached, commands will fail with a timeout instead of blocking. Default is 3 seconds.") |
| 280 | + |
| 281 | + flag.IntVar(&redisPoolSize, redisPoolSizeFlag, 10, "Legacy setting that has been kept for backwards compatibility, you may want to use REDIS_POOL_SIZE_LITERAL going forward. This sets the redis connection pool size, to this value multiplied by the number of CPU available. E.g if this value is 10 and you've 2 CPU the connection pool size will be 20") |
| 282 | + flag.IntVar(&redisPoolSizeLiteral, redisPoolSizeLiteralFlag, 0, "sets the maximum number of socket connections to the literal value passed e.g. setting this to 10 means the connection pool size will be 10. If not specified, this will be set to the default value of 10 per CPU") |
| 283 | + flag.IntVar(&redisPoolTimeoutSeconds, redisPoolTimeoutSecondsFlag, 4, "Amount of time client waits for connection if all connections are busy before returning an error.Default is 4 seconds (default ReadTimeout + 1 second)") |
| 284 | + |
| 285 | + flag.IntVar(&redisMinIdleConns, redisMinIdleConnsFlag, 0, "Minimum number of idle connections which is useful when establishing new connection is slow.") |
| 286 | + flag.IntVar(&redisMaxIdleConns, redisMaxIdleConnsFlag, 0, "MaxIdleConns is the maximum number of idle connections. The idle connections are not closed by default. Default: 0") |
| 287 | + flag.IntVar(&redisMaxActiveConns, redisMaxActiveConnsFlag, 0, "MaxActiveConns is the 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. If the pool is full, the next call to Get() will block until a connection is released.") |
| 288 | + flag.IntVar(&redisConnMaxIdleTimeMinutes, redisConnMaxIdleTimeMinutesFlag, 30, "The maximum amount of time a connection may be idle. Should be less than server's timeout. Expired connections may be closed lazily before reuse. If d <= 0, connections are not closed due to a connection's idle time. -1 disables idle timeout check. Default: 30 minutes") |
| 289 | + flag.IntVar(&redisConnMaxLifetimeMinutes, redisConnMaxLifetimeMinutesFlag, 0, "The maximum amount of time a connection may be reused. Expired connections may be closed lazily before reuse. If <= 0, connections are not closed due to a connection's age. Default: 0") |
218 | 290 |
|
219 | 291 | // Server Config |
220 | 292 | flag.IntVar(&port, portFlag, 8000, "port the relay proxy service is exposed on, default's to 8000") |
@@ -266,6 +338,23 @@ func init() { |
266 | 338 | metricsStreamMaxLenEnv: metricsStreamMaxLenFlag, |
267 | 339 | metricsStreamReadConcurrencyEnv: metricStreamReadConcurrencyFlag, |
268 | 340 | forwardTargetsEnv: forwardTargetsFlag, |
| 341 | + |
| 342 | + redisMaxRetriesEnv: redisMaxRetriesFlag, |
| 343 | + redisMinRetryBackoffMillisecondsEnv: redisMinRetryBackoffMillisecondsFlag, |
| 344 | + redisMaxRetryBackoffMillisecondsEnv: redisMaxRetryBackoffMillisecondsFlag, |
| 345 | + |
| 346 | + redisDialTimeoutSecondsEnv: redisDialTimeoutSecondsFlag, |
| 347 | + redisReadTimeoutSecondsEnv: redisReadTimeoutSecondsFlag, |
| 348 | + redisWriteTimeoutSecondsEnv: redisWriteTimeoutSecondsFlag, |
| 349 | + |
| 350 | + redisPoolSizeLiteralEnv: redisPoolSizeLiteralFlag, |
| 351 | + redisPoolTimeoutSecondsEnv: redisPoolTimeoutSecondsFlag, |
| 352 | + |
| 353 | + redisMinIdleConnsEnv: redisMinIdleConnsFlag, |
| 354 | + redisMaxIdleConnsEnv: redisMaxIdleConnsFlag, |
| 355 | + redisMaxActiveConnsEnv: redisMaxActiveConnsFlag, |
| 356 | + redisConnMaxIdleTimeMinutesEnv: redisConnMaxIdleTimeMinutesFlag, |
| 357 | + redisConnMaxLifetimeMinutesEnv: redisConnMaxLifetimeMinutesFlag, |
269 | 358 | }) |
270 | 359 |
|
271 | 360 | flag.Parse() |
@@ -760,20 +849,55 @@ func newRedisClient(addr string, username string, password string, db int, logge |
760 | 849 | splitAddr[i] = removeRedisScheme(split) |
761 | 850 | } |
762 | 851 |
|
| 852 | + minRetryBackoff := time.Duration(redisMinRetryBackoffMilliseconds) * time.Millisecond |
| 853 | + maxRetryBackoff := time.Duration(redisMaxRetryBackoffMilliseconds) * time.Millisecond |
| 854 | + dialTimeout := time.Duration(redisDialTimeoutSeconds) * time.Second |
| 855 | + readTimeout := time.Duration(redisReadTimeoutSeconds) * time.Second |
| 856 | + writeTimeout := time.Duration(redisWriteTimeoutSeconds) * time.Second |
| 857 | + poolTimeout := time.Duration(redisPoolTimeoutSeconds) * time.Second |
| 858 | + maxIdleTime := time.Duration(redisConnMaxIdleTimeMinutes) * time.Minute |
| 859 | + connMaxLifetime := time.Duration(redisConnMaxLifetimeMinutes) * time.Minute |
| 860 | + |
| 861 | + if poolTimeout < readTimeout { |
| 862 | + poolTimeout = readTimeout + time.Second |
| 863 | + logger.Warn("redis pool timeout is less than readTimeout, setting redis pool timeout to read timeout +1 second", "readTimeout", readTimeout, "poolTimeout", poolTimeout) |
| 864 | + } |
| 865 | + |
| 866 | + // For backwards compatibility by default we use the old method of figuring out the pool size |
| 867 | + // which is the REDIS_POOL_SIZE value multiplied by the number of CPU. |
| 868 | + // |
| 869 | + // However, if REDIS_POOL_SIZE_LITERAL is set then we will use it instead. |
| 870 | + poolSize := redisPoolSize * runtime.NumCPU() |
| 871 | + if redisPoolSizeLiteral >= 0 { |
| 872 | + poolSize = redisPoolSizeLiteral |
| 873 | + } |
| 874 | + |
763 | 875 | opts := redis.UniversalOptions{ |
764 | | - Addrs: splitAddr, |
765 | | - DB: db, |
766 | | - Username: username, |
767 | | - Password: password, |
768 | | - PoolSize: redisPoolSize * runtime.NumCPU(), |
769 | | - TLSConfig: parsed.TLSConfig, |
| 876 | + Addrs: splitAddr, |
| 877 | + DB: db, |
| 878 | + Username: username, |
| 879 | + Password: password, |
| 880 | + PoolSize: poolSize, |
| 881 | + TLSConfig: parsed.TLSConfig, |
| 882 | + MaxRetries: redisMaxRetries, |
| 883 | + MinRetryBackoff: minRetryBackoff, |
| 884 | + MaxRetryBackoff: maxRetryBackoff, |
| 885 | + DialTimeout: dialTimeout, |
| 886 | + ReadTimeout: readTimeout, |
| 887 | + WriteTimeout: writeTimeout, |
| 888 | + PoolTimeout: poolTimeout, |
| 889 | + MinIdleConns: redisMinIdleConns, |
| 890 | + MaxIdleConns: redisMaxIdleConns, |
| 891 | + MaxActiveConns: redisMaxActiveConns, |
| 892 | + ConnMaxIdleTime: maxIdleTime, |
| 893 | + ConnMaxLifetime: connMaxLifetime, |
770 | 894 | } |
771 | 895 |
|
772 | 896 | if redisPassword != "" { |
773 | 897 | opts.Password = redisPassword |
774 | 898 | } |
775 | 899 |
|
776 | | - logger.Info("connecting to redis", "address", redisAddress, "poolSize", opts.PoolSize) |
| 900 | + logger.Info("connecting to redis", "redis_config", fmt.Sprintf("%+v", opts)) |
777 | 901 | return redis.NewUniversalClient(&opts) |
778 | 902 | } |
779 | 903 |
|
|
0 commit comments