Skip to content

Commit

Permalink
[#361] Add a max_connection_age setting
Browse files Browse the repository at this point in the history
This defines how long a connection will live in seconds
- Add a `max_connection_age` member to `struct configuration`. It will be checked upon returned to the pool, or during idle timeout.
- Add new STATE, TRACKER, and Prometheus metric for `max_connection_age`
- Add documentation for `max_connection_age`
- Add a `start_time` member to `struct connection`. Its implementation is similar to `timestamp`
  • Loading branch information
hao-tian-xu authored and hao-tian-xu committed Apr 20, 2023
1 parent 48d7cdf commit 6112ec6
Show file tree
Hide file tree
Showing 14 changed files with 264 additions and 33 deletions.
1 change: 1 addition & 0 deletions doc/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ connection, and move them around in the connection state diagram. The state diag
| `STATE_GRACEFULLY` | The connection will be killed upon return to the pool |
| `STATE_FLUSH` | The connection is being flushed |
| `STATE_IDLE_CHECK` | The connection is being idle timeout checked |
| `STATE_MAX_CONNECTION_AGE` | The connection is being max connection age checked |
| `STATE_VALIDATION` | The connection is being validated |
| `STATE_REMOVE` | The connection is being removed |

Expand Down
1 change: 1 addition & 0 deletions doc/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ The available keys and their accepted values are reported in the table below.
| log_disconnections | `off` | Bool | No | Log disconnects |
| blocking_timeout | 30 | Int | No | The number of seconds the process will be blocking for a connection (disable = 0) |
| idle_timeout | 0 | Int | No | The number of seconds a connection is been kept alive (disable = 0) |
| max_connection_age | 0 | Int | No | The maximum number of seconds that a connection will live (disable = 0) |
| validation | `off` | String | No | Should connection validation be performed. Valid options: `off`, `foreground` and `background` |
| background_interval | 300 | Int | No | The interval between background validation scans in seconds |
| max_retries | 5 | Int | No | The maximum number of iterations to obtain a connection |
Expand Down
4 changes: 2 additions & 2 deletions doc/PIPELINES.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ latency.
__Important__

Make sure that the `blocking_timeout` settings to set to 0. Otherwise active clients
may timeout during their workload. Likewise it is best to disable idle connection timeout by
setting `idle_timeout` to 0.
may timeout during their workload. Likewise it is best to disable idle connection timeout
and max connection age by setting `idle_timeout` and `max_connection_age` to 0.

It is highly recommended that you prefill all connections for each user.

Expand Down
3 changes: 3 additions & 0 deletions doc/man/pgagroal.conf.5.rst
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ blocking_timeout
idle_timeout
The number of seconds a connection is been kept alive (disable = 0). Default is 0

max_connection_age
The maximum number of seconds that a connection will live (disable = 0). Default is 0

validation
Should connection validation be performed. Valid options: off, foreground and background. Default is off

Expand Down
42 changes: 23 additions & 19 deletions src/include/pgagroal.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,16 @@ extern "C" {

#define NUMBER_OF_SECURITY_MESSAGES 5

#define STATE_NOTINIT -2
#define STATE_INIT -1
#define STATE_FREE 0
#define STATE_IN_USE 1
#define STATE_GRACEFULLY 2
#define STATE_FLUSH 3
#define STATE_IDLE_CHECK 4
#define STATE_VALIDATION 5
#define STATE_REMOVE 6
#define STATE_NOTINIT -2
#define STATE_INIT -1
#define STATE_FREE 0
#define STATE_IN_USE 1
#define STATE_GRACEFULLY 2
#define STATE_FLUSH 3
#define STATE_IDLE_CHECK 4
#define STATE_MAX_CONNECTION_AGE 5
#define STATE_VALIDATION 6
#define STATE_REMOVE 7

#define SECURITY_INVALID -2
#define SECURITY_REJECT -1
Expand Down Expand Up @@ -280,6 +281,7 @@ struct connection
int backend_secret; /**< The backend secret */

signed char limit_rule; /**< The limit rule used */
time_t start_time; /**< The start timestamp */
time_t timestamp; /**< The last used timestamp */
pid_t pid; /**< The associated process id */
int fd; /**< The descriptor */
Expand Down Expand Up @@ -359,16 +361,17 @@ struct prometheus
atomic_ulong session_time[HISTOGRAM_BUCKETS]; /**< The histogram buckets */
atomic_ulong session_time_sum; /**< Total session time */

atomic_ulong connection_error; /**< The number of error calls */
atomic_ulong connection_kill; /**< The number of kill calls */
atomic_ulong connection_remove; /**< The number of remove calls */
atomic_ulong connection_timeout; /**< The number of timeout calls */
atomic_ulong connection_return; /**< The number of return calls */
atomic_ulong connection_invalid; /**< The number of invalid calls */
atomic_ulong connection_get; /**< The number of get calls */
atomic_ulong connection_idletimeout; /**< The number of idle timeout calls */
atomic_ulong connection_flush; /**< The number of flush calls */
atomic_ulong connection_success; /**< The number of success calls */
atomic_ulong connection_error; /**< The number of error calls */
atomic_ulong connection_kill; /**< The number of kill calls */
atomic_ulong connection_remove; /**< The number of remove calls */
atomic_ulong connection_timeout; /**< The number of timeout calls */
atomic_ulong connection_return; /**< The number of return calls */
atomic_ulong connection_invalid; /**< The number of invalid calls */
atomic_ulong connection_get; /**< The number of get calls */
atomic_ulong connection_idletimeout; /**< The number of idle timeout calls */
atomic_ulong connection_max_connection_age; /**< The number of max connection age calls */
atomic_ulong connection_flush; /**< The number of flush calls */
atomic_ulong connection_success; /**< The number of success calls */

/**< The number of connection awaiting due to `blocking_timeout` */
atomic_ulong connections_awaiting[NUMBER_OF_LIMITS];
Expand Down Expand Up @@ -451,6 +454,7 @@ struct configuration

int blocking_timeout; /**< The blocking timeout in seconds */
int idle_timeout; /**< The idle timeout in seconds */
int max_connection_age; /**< The max connection age in seconds */
int validation; /**< Validation mode */
int background_interval; /**< Background validation timer in seconds */
int max_retries; /**< The maximum number of retries */
Expand Down
6 changes: 6 additions & 0 deletions src/include/pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ pgagroal_kill_connection(int slot, SSL* ssl);
void
pgagroal_idle_timeout(void);

/**
* Perform max connection age check
*/
void
pgagroal_max_connection_age(void);

/**
* Perform connection validation
*/
Expand Down
6 changes: 6 additions & 0 deletions src/include/prometheus.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ pgagroal_prometheus_connection_get(void);
void
pgagroal_prometheus_connection_idletimeout(void);

/**
* Connection max connection age
*/
void
pgagroal_prometheus_connection_max_connection_age(void);

/**
* Connection awaiting due to `blocking_timeout`.
* Tracks the total awaiting connections and also the
Expand Down
23 changes: 12 additions & 11 deletions src/include/tracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,18 @@ extern "C" {

#define TRACKER_BAD_CONNECTION 9
#define TRACKER_IDLE_TIMEOUT 10
#define TRACKER_INVALID_CONNECTION 11
#define TRACKER_FLUSH 12
#define TRACKER_REMOVE_CONNECTION 13

#define TRACKER_PREFILL 14
#define TRACKER_PREFILL_RETURN 15
#define TRACKER_PREFILL_KILL 16
#define TRACKER_WORKER_RETURN1 17
#define TRACKER_WORKER_RETURN2 18
#define TRACKER_WORKER_KILL1 19
#define TRACKER_WORKER_KILL2 20
#define TRACKER_MAX_CONNECTION_AGE 11
#define TRACKER_INVALID_CONNECTION 12
#define TRACKER_FLUSH 13
#define TRACKER_REMOVE_CONNECTION 14

#define TRACKER_PREFILL 15
#define TRACKER_PREFILL_RETURN 16
#define TRACKER_PREFILL_KILL 17
#define TRACKER_WORKER_RETURN1 18
#define TRACKER_WORKER_RETURN2 19
#define TRACKER_WORKER_KILL1 20
#define TRACKER_WORKER_KILL2 21

#define TRACKER_TX_RETURN_CONNECTION_START 30
#define TRACKER_TX_RETURN_CONNECTION_STOP 31
Expand Down
18 changes: 18 additions & 0 deletions src/libpgagroal/configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ pgagroal_init_configuration(void* shm)

config->blocking_timeout = 30;
config->idle_timeout = 0;
config->max_connection_age = 0;
config->validation = VALIDATION_OFF;
config->background_interval = 300;
config->max_retries = 5;
Expand Down Expand Up @@ -645,6 +646,11 @@ pgagroal_validate_configuration(void* shm, bool has_unix_socket, bool has_main_s
pgagroal_log_warn("pgagroal: Using idle_timeout for the transaction pipeline is not recommended");
}

if (config->max_connection_age > 0)
{
pgagroal_log_warn("pgagroal: Using max_connection_age for the transaction pipeline is not recommended");
}

if (config->validation == VALIDATION_FOREGROUND)
{
pgagroal_log_warn("pgagroal: Using foreground validation for the transaction pipeline is not recommended");
Expand Down Expand Up @@ -2262,6 +2268,7 @@ transfer_configuration(struct configuration* config, struct configuration* reloa

config->blocking_timeout = reload->blocking_timeout;
config->idle_timeout = reload->idle_timeout;
config->max_connection_age = reload->max_connection_age;
config->validation = reload->validation;
config->background_interval = reload->background_interval;
config->max_retries = reload->max_retries;
Expand Down Expand Up @@ -3190,6 +3197,10 @@ pgagroal_write_config_value(char* buffer, char* config_key, size_t buffer_size)
{
return to_int(buffer, config->idle_timeout);
}
else if (!strncmp(key, "max_connection_age", MISC_LENGTH))
{
return to_int(buffer, config->max_connection_age);
}
else if (!strncmp(key, "validation", MISC_LENGTH))
{
return to_validation(buffer, config->validation);
Expand Down Expand Up @@ -3998,6 +4009,13 @@ pgagroal_apply_main_configuration(struct configuration* config,
unknown = true;
}
}
else if (key_in_section("max_connection_age", section, key, true, &unknown))
{
if (as_int(value, &config->max_connection_age))
{
unknown = true;
}
}
else if (key_in_section("validation", section, key, true, &unknown))
{
config->validation = as_validation(value);
Expand Down
2 changes: 2 additions & 0 deletions src/libpgagroal/management.c
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,7 @@ pgagroal_management_write_status(int socket, bool graceful)
case STATE_FREE:
case STATE_FLUSH:
case STATE_IDLE_CHECK:
case STATE_MAX_CONNECTION_AGE:
case STATE_VALIDATION:
case STATE_REMOVE:
total++;
Expand Down Expand Up @@ -914,6 +915,7 @@ pgagroal_management_write_details(int socket)

memset(&details, 0, sizeof(details));

pgagroal_write_long(details, (long)config->connections[i].start_time);
pgagroal_write_long(details, (long)config->connections[i].timestamp);
pgagroal_write_int32(details + 8, (int)config->connections[i].pid);
pgagroal_write_int32(details + 12, (int)config->connections[i].fd);
Expand Down
Loading

0 comments on commit 6112ec6

Please sign in to comment.