pgpool2.git / summary / log / commit / refs

commit    7bfedf9e18bda187fb14d3f9219ce3524a656d22
Author:   Tatsuo Ishii <ishii@postgresql.org>
Date:     Wed Jul 09 13:04:26 2014 +0000

    Add new directive "connect_timeout".
    
    This is for timeout value in milliseconds before giving up to connect
    to backend using connect() system call in
    connect_inet_domain_socket_by_port() which is used for health check
    and creating backend connection.  Since we use non-blocking connect(),
    we use select() if connect() returns "in progress" state. Before the
    timeout value for select() was fixed 1 second, which is not long
    enough for flaky network such as AWS.  So new knob is added to control
    the timeout value.


doc/pgpool-en.html | 13 ++++++++ doc/pgpool-ja.html | 11 +++++++ src/config/pool_config.c | 14 ++++++++ src/config/pool_config.l | 14 ++++++++ src/include/pool_config.h | 1 + src/protocol/pool_connection_pool.c | 53 +++++++++++++++++++----------- src/sample/pgpool.conf.sample | 7 +++- src/sample/pgpool.conf.sample-master-slave | 7 +++- src/sample/pgpool.conf.sample-replication | 7 +++- src/sample/pgpool.conf.sample-stream | 7 +++- src/utils/pool_process_reporting.c | 5 +++ 11 files changed, 116 insertions(+), 23 deletions(-) diff --git a/doc/pgpool-en.html b/doc/pgpool-en.html index a23c138f5..0f893b987 100644 --- a/doc/pgpool-en.html +++ b/doc/pgpool-en.html @@ -1017,6 +1017,19 @@ local0.* /var/log/pgpool.log </p> </dd> +<dt><a name="CONNECT_TIMEOUT"></a>connect_timeout <span class="version">V3.4 -</span></dt> + <dd> + <p>Timeout value in milliseconds before giving up connecting to + backend using connect() system call. Default is 1000 ms (1 + second). Flaky network user may want to increase the value. 0 + means no timeout. Note that this value is not only used for + health check, but also for creating ordinary conection pools. + </p> + <p> + You need to reload pgpool.conf if you change connect_timeout. + </p> + </dd> + <dt><a name="SEARCH_PRIMARY_NODE_TIMEOUT"></a>search_primary_node_timeout <span class="version">V3.3 -</span></dt> <dd> <p>The parameter specifies the maximum amount of time in seconds to search diff --git a/doc/pgpool-ja.html b/doc/pgpool-ja.html index 3323d8f42..410abd139 100644 --- a/doc/pgpool-ja.html +++ b/doc/pgpool-ja.html @@ -1011,6 +1011,17 @@ local0.* /var/log/pgpool.log </p> </dd> +<dt><a name="CONNECT_TIMEOUT"></a>connect_timeout <span class="version">V3.4 -</span></dt> + <dd> + <p>connect()システムコールを使ってバックエンドに接続する際のタイムアウト値をミリ秒単位で指定します。 + デフォルトは1000ミリ秒(1秒)です。不安定なネットワークを使わなければならない場合は、この値を大きくすると良いでしょう。 + 0を指定すると、タイムアウトしません。 + </p> + <p> + <a href="#CONNECT_TIMEOUT">connect_timeout</a>を変更した場合は、pgpool.confの再読込が必要です。 + </p> + </dd> + <dt><a name="SEARCH_PRIMARY_NODE_TIMEOUT"></a>search_primary_node_timeout <span class="version">V3.3 -</span></dt> <dd> <p>このパラメータはフェイルオーバーが起きた時にプライマリノードを検索する際のタイムアウト時間を秒単位で指定します。 diff --git a/src/config/pool_config.c b/src/config/pool_config.c index e05346e06..1eb0591b1 100644 --- a/src/config/pool_config.c +++ b/src/config/pool_config.c @@ -1934,6 +1934,7 @@ int pool_init_config(void) pool_config->health_check_password = ""; pool_config->health_check_max_retries = 0; pool_config->health_check_retry_delay = 1; + pool_config->connect_timeout = 1000; pool_config->sr_check_period = 0; pool_config->sr_check_user = "nobody"; pool_config->sr_check_password = ""; @@ -3136,6 +3137,19 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context) } pool_config->health_check_retry_delay = v; } + else if (!strcmp(key, "connect_timeout") && + CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context)) + { + int v = atoi(yytext); + + if (token != POOL_INTEGER || v < 0) + { + pool_error("pool_config: %s must be equal or higher than 0 numeric value", key); + fclose(fd); + return(-1); + } + pool_config->connect_timeout = v; + } else if (!strcmp(key, "sr_check_period") && CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context)) diff --git a/src/config/pool_config.l b/src/config/pool_config.l index 1256d5131..6f962d6f4 100644 --- a/src/config/pool_config.l +++ b/src/config/pool_config.l @@ -195,6 +195,7 @@ int pool_init_config(void) pool_config->health_check_password = ""; pool_config->health_check_max_retries = 0; pool_config->health_check_retry_delay = 1; + pool_config->connect_timeout = 1000; pool_config->sr_check_period = 0; pool_config->sr_check_user = "nobody"; pool_config->sr_check_password = ""; @@ -1397,6 +1398,19 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context) } pool_config->health_check_retry_delay = v; } + else if (!strcmp(key, "connect_timeout") && + CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context)) + { + int v = atoi(yytext); + + if (token != POOL_INTEGER || v < 0) + { + pool_error("pool_config: %s must be equal or higher than 0 numeric value", key); + fclose(fd); + return(-1); + } + pool_config->connect_timeout = v; + } else if (!strcmp(key, "sr_check_period") && CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context)) diff --git a/src/include/pool_config.h b/src/include/pool_config.h index eb46a9fea..9eb7ea22c 100644 --- a/src/include/pool_config.h +++ b/src/include/pool_config.h @@ -133,6 +133,7 @@ typedef struct { char *health_check_password; /* password for health check username */ int health_check_max_retries; /* health check max retries */ int health_check_retry_delay; /* amount of time to wait between retries */ + int connect_timeout; /* timeout value before giving up connecting to backend */ int sr_check_period; /* streaming replication check period */ char *sr_check_user; /* PostgreSQL user name streaming replication check */ char *sr_check_password; /* password for sr_check_user */ diff --git a/src/protocol/pool_connection_pool.c b/src/protocol/pool_connection_pool.c index e8f90457e..62a350365 100644 --- a/src/protocol/pool_connection_pool.c +++ b/src/protocol/pool_connection_pool.c @@ -5,7 +5,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2013 PgPool Global Development Group + * Copyright (c) 2003-2014 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -521,18 +521,12 @@ int connect_inet_domain_socket_by_port(char *host, int port, bool retry) struct sockaddr_in addr; struct hostent *hp; struct timeval timeout; + struct timeval *tm; fd_set rset, wset; int error; socklen_t socklen; int sts; -#define CONNECT_TIMEOUT_MSEC 1000 /* specify select(2) timeout in milliseconds */ -#define CONNECT_TIMEOUT_SEC CONNECT_TIMEOUT_MSEC/1000 /* seconds part */ -/* microseconds part */ -#define CONNECT_TIMEOUT_MICROSEC (CONNECT_TIMEOUT_SEC == 0?CONNECT_TIMEOUT_MSEC*1000:\ - CONNECT_TIMEOUT_MSEC*1000 - CONNECT_TIMEOUT_SEC*1000*1000) - - fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { @@ -602,30 +596,46 @@ int connect_inet_domain_socket_by_port(char *host, int port, bool retry) */ if (errno != EINPROGRESS && errno != EALREADY) { - pool_error("connect_inet_domain_socket: connect() failed: %s",strerror(errno)); + pool_error("connect_inet_domain_socket(%s:%d): connect() failed: %s", + host, port, strerror(errno)); close(fd); return -1; } - timeout.tv_sec = CONNECT_TIMEOUT_SEC; - timeout.tv_usec = CONNECT_TIMEOUT_MICROSEC; + if (pool_config->connect_timeout == 0) + tm = NULL; + else + { + tm = &timeout; + timeout.tv_sec = pool_config->connect_timeout/1000; + if (timeout.tv_sec == 0) + { + timeout.tv_usec = pool_config->connect_timeout*1000; + } + else + { + timeout.tv_usec = (pool_config->connect_timeout - timeout.tv_sec*1000)*1000; + } + } + FD_ZERO(&rset); FD_SET(fd, &rset); FD_ZERO(&wset); FD_SET(fd, &wset); - sts = select(fd+1, &rset, &wset, NULL, &timeout); + sts = select(fd+1, &rset, &wset, NULL, tm); if (sts == 0) { /* select timeout */ if (retry) { - pool_log("connect_inet_domain_socket: select() timed out. retrying..."); + pool_log("connect_inet_domain_socket(%s:%d): select() timed out. retrying...", + host, port); continue; } else { - pool_error("connect_inet_domain_socket: select() timed out"); + pool_error("connect_inet_domain_socket(%s:%d): select() timed out", host, port); close(fd); return -1; } @@ -647,7 +657,8 @@ int connect_inet_domain_socket_by_port(char *host, int port, bool retry) if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &socklen) < 0) { /* Solaris returns error in this case */ - pool_error("connect_inet_domain_socket: getsockopt() failed: %s", strerror(errno)); + pool_error("connect_inet_domain_socket(%s:%d): getsockopt() failed: %s", + host, port, strerror(errno)); close(fd); return -1; } @@ -655,14 +666,16 @@ int connect_inet_domain_socket_by_port(char *host, int port, bool retry) /* Non Solaris case */ if (error != 0) { - pool_error("connect_inet_domain_socket: getsockopt() detected error: %s", strerror(error)); + pool_error("connect_inet_domain_socket(%s:%d): getsockopt() detected error: %s", + host, port, strerror(error)); close(fd); return -1; } } else { - pool_error("connect_inet_domain_socket: both read data and write data was not set"); + pool_error("connect_inet_domain_socket(%s:%d): both read data and write data was not set", + host, port); close(fd); return -1; } @@ -671,10 +684,12 @@ int connect_inet_domain_socket_by_port(char *host, int port, bool retry) { if((errno == EINTR && retry) || errno == EAGAIN) { - pool_log("connect_inet_domain_socket: select() interrupted. retrying..."); + pool_log("connect_inet_domain_socket(%s:%d): select() interrupted. retrying...", + host, port); continue; } - pool_log("connect_inet_domain_socket: select() interrupted"); + pool_log("connect_inet_domain_socket(%s:%d): select() interrupted", + host, port); close(fd); return -1; } diff --git a/src/sample/pgpool.conf.sample b/src/sample/pgpool.conf.sample index 6a0f6c4c1..9c8e845ed 100644 --- a/src/sample/pgpool.conf.sample +++ b/src/sample/pgpool.conf.sample @@ -391,7 +391,12 @@ health_check_max_retries = 0 # Maximum number of times to retry a failed health check before giving up. health_check_retry_delay = 1 # Amount of time to wait (in seconds) between retries. - +connect_timeout = 1000 + # Timeout value in milliseconds before giving up to connect to backend. + # Default is 1000 ms (1 second). Flaky network user may want to increase + # the value. 0 means no timeout. + # Note that this value is not only used for health check, + # but also for ordinary conection to backend. #------------------------------------------------------------------------------ # FAILOVER AND FAILBACK diff --git a/src/sample/pgpool.conf.sample-master-slave b/src/sample/pgpool.conf.sample-master-slave index 0f4beec28..3c7be68e8 100644 --- a/src/sample/pgpool.conf.sample-master-slave +++ b/src/sample/pgpool.conf.sample-master-slave @@ -390,7 +390,12 @@ health_check_max_retries = 0 # Maximum number of times to retry a failed health check before giving up. health_check_retry_delay = 1 # Amount of time to wait (in seconds) between retries. - +connect_timeout = 1000 + # Timeout value in milliseconds before giving up to connect to backend. + # Default is 1000 ms (1 second). Flaky network user may want to increase + # the value. 0 means no timeout. + # Note that this value is not only used for health check, + # but also for ordinary conection to backend. #------------------------------------------------------------------------------ # FAILOVER AND FAILBACK diff --git a/src/sample/pgpool.conf.sample-replication b/src/sample/pgpool.conf.sample-replication index e6334d058..73a4c4c69 100644 --- a/src/sample/pgpool.conf.sample-replication +++ b/src/sample/pgpool.conf.sample-replication @@ -390,7 +390,12 @@ health_check_max_retries = 0 # Maximum number of times to retry a failed health check before giving up. health_check_retry_delay = 1 # Amount of time to wait (in seconds) between retries. - +connect_timeout = 1000 + # Timeout value in milliseconds before giving up to connect to backend. + # Default is 1000 ms (1 second). Flaky network user may want to increase + # the value. 0 means no timeout. + # Note that this value is not only used for health check, + # but also for ordinary conection to backend. #------------------------------------------------------------------------------ # FAILOVER AND FAILBACK diff --git a/src/sample/pgpool.conf.sample-stream b/src/sample/pgpool.conf.sample-stream index e2616f7e2..fa6551f8f 100644 --- a/src/sample/pgpool.conf.sample-stream +++ b/src/sample/pgpool.conf.sample-stream @@ -391,7 +391,12 @@ health_check_max_retries = 0 # Maximum number of times to retry a failed health check before giving up. health_check_retry_delay = 1 # Amount of time to wait (in seconds) between retries. - +connect_timeout = 1000 + # Timeout value in milliseconds before giving up to connect to backend. + # Default is 1000 ms (1 second). Flaky network user may want to increase + # the value. 0 means no timeout. + # Note that this value is not only used for health check, + # but also for ordinary conection to backend. #------------------------------------------------------------------------------ # FAILOVER AND FAILBACK diff --git a/src/utils/pool_process_reporting.c b/src/utils/pool_process_reporting.c index 4a188a75a..33d116004 100644 --- a/src/utils/pool_process_reporting.c +++ b/src/utils/pool_process_reporting.c @@ -558,6 +558,11 @@ POOL_REPORT_CONFIG* get_config(int *nrows) StrNCpy(status[i].desc, "health check retry delay", POOLCONFIG_MAXDESCLEN); i++; + StrNCpy(status[i].name, "connect_timeout", POOLCONFIG_MAXNAMELEN); + snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->connect_timeout); + StrNCpy(status[i].desc, "connect timeout", POOLCONFIG_MAXDESCLEN); + i++; + /* FAILOVER AND FAILBACK */ StrNCpy(status[i].name, "failover_command", POOLCONFIG_MAXNAMELEN); [parent: 69268703ed85]