]> granicus.if.org Git - pgbouncer/commitdiff
Reserve pool implementation.
authorMarko Kreen <markokr@gmail.com>
Fri, 2 Jan 2009 10:54:47 +0000 (10:54 +0000)
committerMarko Kreen <markokr@gmail.com>
Fri, 2 Jan 2009 10:54:47 +0000 (10:54 +0000)
Allow to increased pool size in case main pool size
cannot serve clients anymore.

This allows to continue use of small pool_size, which
smooths small peaks, while also handling large peaks.

(Eg, one bouncer server down, others need to handle load.)

doc/config.txt
etc/pgbouncer.ini
include/bouncer.h
src/admin.c
src/janitor.c
src/loader.c
src/main.c
src/objects.c

index aa8f81e4a2ea5d29a9a0dc6423e2263d9400c4f3..85d666cf780668972bfb9fda6565868d121e6b4e 100644 (file)
@@ -139,6 +139,22 @@ per-database config.
 
 Default: 20
 
+==== reserve_pool_size ====
+
+How many additional connections to allow to a pool.
+
+How many server connection to allow per user/database pair. Can be overrided in
+per-database config.  0 disables.
+
+Default: 0 (disabled)
+
+==== reserve_pool_timeout ====
+
+If a client has not been services in this many seconds, pgbouncer enables
+use of additional connections from reserve pool.  0 disables.
+
+Default: 5
+
 ==== server_round_robin ====
 
 By default, pgbouncer reuses server connections in LIFO manner, so that few
index 7c38f3429089ed4039c72d9083fafb6067605c03..87bae3afae8e48d4d9053ff385e50cc9575d7050 100644 (file)
@@ -10,6 +10,8 @@ bardb = host=127.0.0.1 dbname=bazdb
 ; acceess to dest database will go with single user
 forcedb = host=127.0.0.1 port=300 user=baz password=foo client_encoding=UNICODE datestyle=ISO connect_query='SELECT 1'
 
+nondefaultdb = pool_size=50 reserve_pool=10
+
 ;; Configuation section
 [pgbouncer]
 
@@ -93,6 +95,12 @@ server_check_delay = 10
 max_client_conn = 100
 default_pool_size = 20
 
+; how many additional connection to allow in case of trouble
+;reserve_pool_size = 5
+
+; if a clients needs to wait more than this many seconds, use reserve pool
+;reserve_pool_timeout = 3
+
 log_connections = 1
 log_disconnections = 1
 
index b4239ace39d60a37e6aebe475beebf5a470fa8c6..87a5a6ce8851b71e67bf2fa674b6286513406951 100644 (file)
@@ -232,6 +232,7 @@ struct PgDatabase {
        char unix_socket_dir[UNIX_PATH_MAX]; /* custom unix socket dir */
 
        int pool_size;          /* max server connections in one pool */
+       int res_pool_size;      /* additional server connections in case of trouble */
 
        const char *dbname;     /* server-side name, pointer to inside startup_msg */
 
@@ -309,6 +310,8 @@ extern int cf_listen_port;
 extern int cf_pool_mode;
 extern int cf_max_client_conn;
 extern int cf_default_pool_size;
+extern int cf_res_pool_size;
+extern usec_t cf_res_pool_timeout;
 
 extern char * cf_autodb_connstr;
 extern usec_t cf_autodb_idle_timeout;
index 55f559b118cd5181857b11c22416ceac338b6cf2..e757474461e2086f8f99caa1e2a6d4776f440661 100644 (file)
@@ -415,9 +415,9 @@ static bool admin_show_databases(PgSocket *admin, const char *arg)
                return true;
        }
 
-       pktbuf_write_RowDescription(buf, "ssissi",
+       pktbuf_write_RowDescription(buf, "ssissii",
                                    "name", "host", "port",
-                                   "database", "force_user", "pool_size");
+                                   "database", "force_user", "pool_size", "reserve_pool");
        statlist_for_each(item, &database_list) {
                db = container_of(item, PgDatabase, head);
 
@@ -430,7 +430,8 @@ static bool admin_show_databases(PgSocket *admin, const char *arg)
                pktbuf_write_DataRow(buf, "ssissi",
                                     db->name, host, db->addr.port,
                                     db->dbname, f_user,
-                                    db->pool_size);
+                                    db->pool_size,
+                                    db->res_pool_size);
        }
        admin_flush(admin, buf, "SHOW");
        return true;
index c8e1217e77c924791990728e1339f6640bfca76a..8ec9b47d280cbb0a506d595988f86e0f9b22f9b7 100644 (file)
@@ -403,7 +403,7 @@ static void check_pool_size(PgPool *pool)
                 * statlist_count(&pool->new_server_list)
                 */
 
-       int many = cur - pool->db->pool_size;
+       int many = cur - (pool->db->pool_size + pool->db->res_pool_size);
 
        Assert(pool->db->pool_size >= 0);
 
@@ -591,10 +591,14 @@ void config_postprocess(void)
 
        statlist_for_each_safe(item, &database_list, tmp) {
                db = container_of(item, PgDatabase, head);
-               if (db->db_dead)
+               if (db->db_dead) {
                        kill_database(db);
-               else if (db->pool_size < 0)
+                       continue;
+               }
+               if (db->pool_size < 0)
                        db->pool_size = cf_default_pool_size;
+               if (db->res_pool_size < 0)
+                       db->res_pool_size = cf_res_pool_size;
        }
 }
 
index 5c64f0fe495c5befbfd301e964ca5c3175792fd3..5a8a262fef1db2108510b54c5056d30bc7da9b35 100644 (file)
@@ -173,6 +173,7 @@ void parse_database(char *name, char *connstr)
        PktBuf buf;
        PgDatabase *db;
        int pool_size = -1;
+       int res_pool_size = -1;
 
        char *dbname = name;
        char *host = NULL;
@@ -220,6 +221,8 @@ void parse_database(char *name, char *connstr)
                        timezone = val;
                else if (strcmp("pool_size", key) == 0)
                        pool_size = atoi(val);
+               else if (strcmp("reserve_pool", key) == 0)
+                       res_pool_size = atoi(val);
                else if (strcmp("connect_query", key) == 0)
                        connect_query = val;
                else {
@@ -319,6 +322,7 @@ void parse_database(char *name, char *connstr)
 
        /* if pool_size < 0 it will be set later */
        db->pool_size = pool_size;
+       db->res_pool_size = res_pool_size;
        db->addr.port = v_port;
        db->addr.ip_addr.s_addr = v_addr;
        db->addr.is_unix = host ? 0 : 1;
index 2209cfc93665f8f554f171e2253a494338d35976..94721762ff2dca7bacb7bc6c5891c6eb8d93833d 100644 (file)
@@ -91,6 +91,8 @@ char *cf_auth_file = "unconfigured_file";
 
 int cf_max_client_conn = 100;
 int cf_default_pool_size = 20;
+int cf_res_pool_size = 0;
+usec_t cf_res_pool_timeout = 5;
 
 char *cf_server_reset_query = "";
 char *cf_server_check_query = "select 1";
@@ -143,6 +145,8 @@ ConfElem bouncer_params[] = {
 {"pool_mode",          true, {get_mode, set_mode}},
 {"max_client_conn",    true, CF_INT, &cf_max_client_conn},
 {"default_pool_size",  true, CF_INT, &cf_default_pool_size},
+{"reserve_pool_size",  true, CF_INT, &cf_res_pool_size},
+{"reserve_pool_timeout",true, CF_INT, &cf_res_pool_timeout},
 {"syslog",             true, CF_INT, &cf_syslog},
 {"syslog_facility",    true, CF_STR, &cf_syslog_facility},
 #ifndef WIN32
index 8799ddd0cd4ff9ff263f7418be50ab2b67381aa9..18f9930993601c3c6ceae61804860438486c1791 100644 (file)
@@ -331,6 +331,8 @@ PgDatabase *register_auto_database(const char *name)
                /* do not forget to check pool_size like in config_postprocess */
                if (db->pool_size < 0)
                        db->pool_size = cf_default_pool_size;
+               if (db->res_pool_size < 0)
+                       db->res_pool_size = cf_res_pool_size;
        }
 
        return db;
@@ -772,11 +774,23 @@ void launch_new_connection(PgPool *pool)
        /* is it allowed to add servers? */
        total = pool_server_count(pool);
        if (total >= pool->db->pool_size && pool->welcome_msg_ready) {
+               /* should we use reserve pool? */
+               if (cf_res_pool_timeout && pool->db->res_pool_size) {
+                       usec_t now = get_cached_time();
+                       PgSocket *c = first_socket(&pool->waiting_client_list);
+                       if (c && (now - c->request_time) >= cf_res_pool_timeout) {
+                               if (total < pool->db->pool_size + pool->db->res_pool_size) {
+                                       log_debug("reserve_pool activated");
+                                       goto allow_new;
+                               }
+                       }
+               }
                log_debug("launch_new_connection: pool full (%d >= %d)",
                                total, pool->db->pool_size);
                return;
        }
 
+allow_new:
        /* get free conn object */
        server = obj_alloc(server_cache);
        if (!server) {