diff --git a/src/config/pool_config_variables.c b/src/config/pool_config_variables.c index cd42b1f..2e67e2a 100644 --- a/src/config/pool_config_variables.c +++ b/src/config/pool_config_variables.c @@ -503,6 +503,16 @@ static struct config_bool ConfigureNamesBool[] = }, { + {"prefer_lower_delay_standby", CFGCXT_RELOAD, STREAMING_REPLICATION_CONFIG, + "If the load balance node is delayed over delay_threshold on SR, pgpool find another standby node which is lower delayed.", + CONFIG_VAR_TYPE_BOOL, false, 0 + }, + &g_pool_config.prefer_lower_delay_standby, + false, + NULL, NULL, NULL + }, + + { {"connection_cache", CFGCXT_INIT, CONNECTION_POOL_CONFIG, "Caches connections to backends.", CONFIG_VAR_TYPE_BOOL, false, 0 diff --git a/src/context/pool_query_context.c b/src/context/pool_query_context.c index 6635369..5a3f657 100644 --- a/src/context/pool_query_context.c +++ b/src/context/pool_query_context.c @@ -547,8 +547,10 @@ pool_where_to_send(POOL_QUERY_CONTEXT * query_context, char *query, Node *node) */ /* - * If replication delay is too much, we prefer to send to - * the primary. + * As streaming replication delay is too much, if + * prefer_lower_delay_standby is true then elect new + * load balance node which is lower delayed, + * false then send to the primary. */ if (STREAM && pool_config->delay_threshold && @@ -558,7 +560,12 @@ pool_where_to_send(POOL_QUERY_CONTEXT * query_context, char *query, Node *node) (errmsg("could not load balance because of too much replication delay"), errdetail("destination = %d for query= \"%s\"", dest, query))); - pool_set_node_to_be_sent(query_context, PRIMARY_NODE_ID); + if (prefer_lower_delay_standby){ + session_context->load_balance_node_id = select_load_balancing_node(); + pool_set_node_to_be_sent(query_context, session_context->load_balance_node_id); + } else { + pool_set_node_to_be_sent(query_context, PRIMARY_NODE_ID); + } } /* diff --git a/src/include/pool_config.h b/src/include/pool_config.h index d473dc1..a5698d5 100644 --- a/src/include/pool_config.h +++ b/src/include/pool_config.h @@ -304,6 +304,9 @@ typedef struct * that health_check_period required to be * greater than 0 to enable the * functionality. */ + + bool prefer_lower_delay_standby; + LogStandbyDelayModes log_standby_delay; /* how to log standby lag */ bool connection_cache; /* cache connection pool? */ int health_check_timeout; /* health check timeout */ diff --git a/src/protocol/pool_pg_utils.c b/src/protocol/pool_pg_utils.c index 904350d..6f5909f 100644 --- a/src/protocol/pool_pg_utils.c +++ b/src/protocol/pool_pg_utils.c @@ -300,6 +300,7 @@ select_load_balancing_node(void) POOL_SESSION_CONTEXT *ses = pool_get_session_context(false); int tmp; int no_load_balance_node_id = -2; + BackendInfo *bkinfo; /* * -2 indicates there's no database_redirect_preference_list. -1 indicates @@ -386,6 +387,39 @@ select_load_balancing_node(void) if (suggested_node_id >= 0) { /* + * If Streaming Replication mode and delay_threshold and + * prefer_lower_delay_standby is true, we choose lower delayed + * node if suggested_node is standby and delayed over delay_threshold. + */ + bkinfo = pool_get_node_info(suggested_node_id); + if ( STREAM && + (suggested_node_id != PRIMARY_NODE_ID) && + pool_config->prefer_lower_delay_standby && + pool_config->delay_threshold && + (bkinfo->standby_delay > pool_config->delay_threshold) ) + { + selected_slot = PRIMARY_NODE_ID; + for ( i = 0; i < NUM_BACKENDS; i++){ + bkinfo = pool_get_node_info(i); + if ( VALID_BACKEND(i) && + !IS_PRIMARY_NODE_ID(i) && + (bkinfo->standby_delay < pool_config->delay_threshold) && + bkinfo->backend_weight > 0 ) + { + selected_slot = i; + break; + } + } + ereport(DEBUG1, + (errmsg("selecting load balance node"), + errdetail("suggested backend id %d is streaming delayed over delay_threshold", suggested_node_id))); + ereport(DEBUG1, + (errmsg("selecting load balance node"), + errdetail("selected backend id is %d", selected_slot))); + return selected_slot; + } + + /* * If the weight is bigger than random rate then send to * suggested_node_id. If the weight is less than random rate then * choose load balance node from other nodes. @@ -457,6 +491,36 @@ select_load_balancing_node(void) total_weight += BACKEND_INFO(i).backend_weight; } } + + /* + * If Streaming Replication mode and delay_threshold and + * prefer_lower_delay_standby is true, we choose lower delayed + * node if suggested_node is standby and delayed over delay_threshold. + */ + bkinfo = pool_get_node_info(selected_slot); + if ( STREAM && + pool_config->prefer_lower_delay_standby && + pool_config->delay_threshold && + (bkinfo->standby_delay > pool_config->delay_threshold) ) + { + ereport(DEBUG1, + (errmsg("selecting load balance node"), + errdetail("selected backend id %d is streaming delayed over delay_threshold", selected_slot))); + + selected_slot = PRIMARY_NODE_ID; + for ( i = 0; i < NUM_BACKENDS; i++){ + bkinfo = pool_get_node_info(i); + if ( !IS_PRIMARY_NODE_ID(i) && + VALID_BACKEND(i) && + (bkinfo->standby_delay < pool_config->delay_threshold) && + (bkinfo->backend_weight > 0) ) + { + selected_slot = i; + break; + } + } + } + ereport(DEBUG1, (errmsg("selecting load balance node"), errdetail("selected backend id is %d", selected_slot)));