[pgpool-hackers: 402] KeepAlive between pgpool and postgresql

Sergey Logvinov serge.logvinov at gmail.com
Thu Nov 14 13:54:55 JST 2013


Code to allow tcp keepalive connection. It helps to define dead postgres
connections.

based on ticket #83

Recommended params for web server

pg_keepalives_idle     = 10     # TCP_KEEPIDLE, in seconds;
pg_keepalives_interval = 3     # TCP_KEEPINTVL, in seconds;
pg_keepalives_count    = 5     # TCP_KEEPCNT;
pg_syn_count           = 3     # TCP_SYNCNT


TCP_SYNCNT work on linux?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.sraoss.jp/pipermail/pgpool-hackers/attachments/20131114/a38fd52a/attachment.html>
-------------- next part --------------
diff --git a/pool_config.h b/pool_config.h
index a5a48f1..e775555 100644
--- a/pool_config.h
+++ b/pool_config.h
@@ -75,6 +75,14 @@ typedef struct {
 	int client_idle_limit;		/* If client_idle_limit is n (n > 0), the client is forced to be
 								   disconnected after n seconds idle */
 	int authentication_timeout; /* maximum time in seconds to complete client authentication */
+
+	// TCP Keepalives for connect to PostgreSQL
+	//   see "man 7 tcp" for details 
+	int pg_keepalives_idle;		/* TCP_KEEPIDLE 	*/
+	int pg_keepalives_interval; /* TCP_KEEPINTVL 	*/
+	int pg_keepalives_count;    /* TCP_KEEPCNT 		*/
+	int pg_syn_count;			/* TCP_SYNCNT		*/
+
     int	max_pool;	/* max # of connection pool per child */
     char *logdir;		/* logging directory */
     char *log_destination;      /* log destination: stderr or syslog */
diff --git a/pool_config.l b/pool_config.l
index b560e65..5c141c8 100644
--- a/pool_config.l
+++ b/pool_config.l
@@ -156,6 +156,12 @@ int pool_init_config(void)
 	pool_config->connection_life_time = 0;
 	pool_config->child_max_connections = 0;
 	pool_config->authentication_timeout = 60;
+  	pool_config->pg_keepalives_idle = 0;
+  	pool_config->pg_keepalives_interval = 0;
+  	pool_config->pg_keepalives_count = 0;
+  	pool_config->pg_syn_count = 0;
 	pool_config->logdir = DEFAULT_LOGDIR;
     pool_config->logsyslog = 0;
     pool_config->log_destination = "stderr";
@@ -658,6 +665,58 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
 			}
 			pool_config->authentication_timeout = v;
 		}
+		else if (!strcmp(key, "pg_keepalives_idle") &&
+				 CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context))
+		{
+			int v = atoi(yytext);
+
+			if (token != POOL_INTEGER || v < 0)
+			{
+				pool_error("pool_config: %s must be higher or equal to 0 numeric value", key);
+				fclose(fd);
+				return(-1);
+			}
+			pool_config->pg_keepalives_idle = v;
+		}
+		else if (!strcmp(key, "pg_keepalives_interval") &&
+				 CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context))
+		{
+			int v = atoi(yytext);
+
+			if (token != POOL_INTEGER || v < 0)
+			{
+				pool_error("pool_config: %s must be higher or equal to 0 numeric value", key);
+				fclose(fd);
+				return(-1);
+			}
+			pool_config->pg_keepalives_interval = v;
+		}
+		else if (!strcmp(key, "pg_keepalives_count") &&
+				 CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context))
+		{
+			int v = atoi(yytext);
+
+			if (token != POOL_INTEGER || v < 0)
+			{
+				pool_error("pool_config: %s must be higher or equal to 0 numeric value", key);
+				fclose(fd);
+				return(-1);
+			}
+			pool_config->pg_keepalives_count = v;
+		}
+		else if (!strcmp(key, "pg_syn_count") &&
+				 CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context))
+		{
+			int v = atoi(yytext);
+
+			if (token != POOL_INTEGER || v < 0)
+			{
+				pool_error("pool_config: %s must be higher or equal to 0 numeric value", key);
+				fclose(fd);
+				return(-1);
+			}
+			pool_config->pg_syn_count = v;
+		}
 		else if (!strcmp(key, "max_pool") && CHECK_CONTEXT(INIT_CONFIG, context))
 		{
 			int v = atoi(yytext);
diff --git a/pool_connection_pool.c b/pool_connection_pool.c
index 47faac9..4d3c1b6 100644
--- a/pool_connection_pool.c
+++ b/pool_connection_pool.c
@@ -532,15 +537,41 @@ int connect_inet_domain_socket_by_port(char *host, int port, bool retry)
 	}
 
 	/* set nodelay */
-	if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
-				   (char *) &on,
-				   sizeof(on)) < 0)
+	if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0)
 	{
 		pool_error("connect_inet_domain_socket_by_port: setsockopt() failed: %s", strerror(errno));
 		close(fd);
 		return -1;
 	}
 
+	/* set keepalive */
+	if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0)
+	{
+		pool_error("connect_inet_domain_socket_by_port: setsockopt() failed: %s", strerror(errno));
+		close(fd);
+		return -1;
+	}
+	else
+	{
+	    int keepalive_idle     = pool_config->pg_keepalives_idle;
+	    int keepalive_count    = pool_config->pg_keepalives_count;
+	    int keepalive_interval = pool_config->pg_keepalives_interval;
+
+		if (keepalive_idle && setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &keepalive_idle, sizeof(int)) < 0)
+			pool_error("connect_inet_domain_socket_by_port: setsockopt(TCP_KEEPIDLE) failed: %s", strerror(errno));
+
+		if (keepalive_count && setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &keepalive_count, sizeof(int)) < 0)
+			pool_error("connect_inet_domain_socket_by_port: setsockopt(TCP_KEEPCNT) failed: %s", strerror(errno));
+
+		if (keepalive_interval && setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &keepalive_interval, sizeof(int)) < 0)
+			pool_error("connect_inet_domain_socket_by_port: setsockopt(TCP_KEEPINTVL) failed: %s", strerror(errno));
+	}
+
+#ifdef TCP_SYNCNT
+	if (pool_config->pg_syn_count && setsockopt(fd, SOL_TCP, TCP_SYNCNT, &pool_config->pg_syn_count, sizeof(int)) < 0)
+		pool_error("connect_inet_domain_socket_by_port: setsockopt(TCP_SYNCNT) failed: %s", strerror(errno));
+#endif
+
 	memset((char *) &addr, 0, sizeof(addr));
 	addr.sin_family = AF_INET;


More information about the pgpool-hackers mailing list