Specifies the list of <replaceable>"database-name:node id"</replaceable> pairs
to send <acronym>SELECT</acronym> queries to a particular backend
node for a particular database connection.
+-->
+特定のデータベース接続で<acronym>SELECT</acronym>クエリが指定したロードバランス比率で特定のバックエンドノードに送信されるように、"<replaceable>データベース名:ノードID(比率)</replaceable>"ペアのリストを指定します。ロードバランス比率は0-1の間の値を指定します。
+比率の指定を省略した場合は、デフォルトの1.0となります。
+ </para>
+ <para>
+<!--
For example, by specifying "test:1", <productname>Pgpool-II</productname>
will redirect all <acronym>SELECT</acronym> queries to the backend node of ID 1 for
the connection to "test" database.
You can specify multiple <replaceable>"database name:node id"</replaceable> pair by separating them
using comma (,).
-->
-特定のデータベース接続では<acronym>SELECT</acronym>クエリが特定のバックエンドノードに送信されるように、"<replaceable>データベース名:ノードID</replaceable>"ペアのリストを指定します。
-たとえば"test:1"とした場合、"test"データベースへの接続においては、<productname>Pgpool-II</productname>は全ての<acronym>SELECT</acronym>クエリをIDが1のバックエンドノードに送信します。
+たとえば"test:1(0.5)"とした場合、"test"データベースへの接続においては、<productname>Pgpool-II</productname>は50%の<acronym>SELECT</acronym>クエリをIDが1のバックエンドノードに送信します。
複数の"<replaceable>データベース名:ノードID</replaceable>"のペアを カンマ(,)で区切って指定することができます。
</para>
<para>
if <emphasis>"standby"</emphasis> is specified, one of the standby nodes are selected randomly
based on weights.
-->
-データベース名には正規表現を指定することできます。
+ã\83\87ã\83¼ã\82¿ã\83\99ã\83¼ã\82¹å\90\8dã\81«ã\81¯æ£è¦\8f表ç\8f¾ã\82\92æ\8c\87å®\9aã\81\99ã\82\8bã\81\93ã\81¨ã\81\8cã\81§ã\81\8dã\81¾ã\81\99ã\80\82
<replaceable>ノードID</replaceable>には特別なキーワードを使うことができます。
"<emphasis>primary</emphasis>"が指定された場合にはクエリはプライマリノードに送られます。
-また、"<emphasis>standby</emphasis>"が指定された場合はスタンバイノードのうちどれかをウェイトに応じてランダムに選択します。
+また、"<emphasis>standby</emphasis>"が指定された場合はスタンバイノードのうちどれかをウェイト(<xref linkend="guc-backend-weight">)に応じてランダムに選択します。
</para>
<example id="example-database-redirect-list">
Route all <acronym>SELECT</acronym> queries on <literal>mydb0</literal> or on
<literal>mydb1</literal> databases to backend node of ID 1.
-->
-全ての<literal>mydb0</literal>または<literal>mydb1</literal>データベースにおける<acronym>SELECT</acronym>クエリはIDが1のバックエンドノードに送る。
+全ての<literal>mydb0</literal>または<literal>mydb1</literal>データベースにおける30%の<acronym>SELECT</acronym>クエリはIDが1のバックエンドノードに送る。
</para>
</listitem>
<listitem>
-->
<xref linkend="guc-database-redirect-preference-list">は以下のように設定します。
<programlisting>
-database_redirect_preference_list = 'postgres:primary,mydb[01]:1,mydb2:standby'
+database_redirect_preference_list = 'postgres:primary,mydb[01]:1(0.3),mydb2:standby'
</programlisting>
</para>
</example>
to send <acronym>SELECT</acronym> queries to a particular backend
node for a particular client application connection.
-->
-特定のクライアントアプリケーションの接続では<acronym>SELECT</acronym>クエリが特定のバックエンドノードに送信されるように、"<replaceable>アプリケーション名:ノードID</replaceable>"ペアのリストを指定します。
+特定のクライアントアプリケーションの接続で<acronym>SELECT</acronym>クエリが指定したロードバランス比率で特定のバックエンドノードに送信されるように、"<replaceable>アプリケーション名:ノードID(比率)</replaceable>"ペアのリストを指定します。
</para>
<note>
-->
<xref linkend="guc-app-name-redirect-preference-list">の記法は<xref linkend="guc-database-redirect-preference-list">と同じですので、アプリケーション名には正規表現も使用できます。
同様に特別なキーワード"<emphasis>primary</emphasis>"はプライマリノードを、"<emphasis>standby</emphasis>"はスタンバイサーバのいずれかを意味します。
+ロードバランス比率は0-1の間の値を指定します。ロードバランス比率の指定を省略した場合は、デフォルトの1.0となります。
</para>
<example id="example-app-name-redirect-list">
Route all <acronym>SELECT</acronym> queries from <literal>myapp1</literal>
client to backend node of ID 1.
-->
-全ての<literal>myapp1</literal>クライアントからの<acronym>SELECT</acronym>クエリはIDが1のバックエンドノードに送る。
+全ての<literal>myapp1</literal>クライアントからの30%の<acronym>SELECT</acronym>クエリはIDが1のバックエンドノードに送る。
</para>
</listitem>
<listitem>
-->
<xref linkend="guc-app-name-redirect-preference-list">は以下のように設定します。
<programlisting>
-app_name_redirect_preference_list = 'psql:primary,myapp1:1,myapp2:standby'
+app_name_redirect_preference_list = 'psql:primary,myapp1:1(0.3),myapp2:standby'
</programlisting>
</para>
</example>
-->
<xref linkend="guc-app-name-redirect-preference-list">は、<xref linkend="guc-database-redirect-preference-list">よりも優先されます。
</para>
+ <para>
+<!--
+ For example, if you set
+ <literal>database_redirect_preference_list = 'postgres:standby(1.0)'</literal> and
+ <literal>app_name_redirect_preference_list = 'psql:primary(1.0)'</literal>,
+ all SELECT from psql client on postgres database will be sent to primary backend node.
+-->
+たとえば、
+<literal>database_redirect_preference_list = 'postgres:standby(1.0)'</literal>、
+<literal>app_name_redirect_preference_list = 'myapp1:primary(1.0)'</literal>
+と設定した場合、アプリケーション<literal>myapp1</literal>、<literal>postgres</literal>データベースでの<literal>SELECT</literal>はプライマリバックエンドノードに送られます。
+ </para>
+ </note>
+
+ <note>
+ <para>
+<!--
+ In the settings of <xref linkend="guc-app-name-redirect-preference-list"> and
+ <xref linkend="guc-database-redirect-preference-list">, when multiple database
+ names and application names are matched, the first setting will be used.
+-->
+<xref linkend="guc-app-name-redirect-preference-list">及び<xref linkend="guc-database-redirect-preference-list">の設定では、複数のデータベース名やアプリケーション名にマッチした場合、最初の設定が反映されます。
+ </para>
+ <para>
+<!--
+ For example, if you set
+ database_redirect_preference_list = 'postgres:primary,postgres:standby',
+ "postgres: primary" will be used.
+-->
+たとえば、
+<literal>database_redirect_preference_list = 'postgres:primary,postgres:standby'</literal>
+と設定した場合、<literal>postgres:primary</literal>の設定が反映されます。
+ </para>
</note>
<caution>
If you want to use the <xref linkend="guc-app-name-redirect-preference-list">
feature through <acronym>JDBC</acronym>, use postgreSQL-9.4 or later version of the driver.
-->
-<acronym>JDBC</acronym>ドライバのpostgresql-9.3以前のバージョンでは、<acronym>JDBC</acronym>ドライバの"<literal>ApplicationName</literal>" と "<literal>assumeMinServerVersion=9.0</literal>"オプションを指定してもスタートアップパケットの中にアプリケーション名を含ません。
+<acronym>JDBC</acronym>ã\83\89ã\83©ã\82¤ã\83\90ã\81®postgresql-9.3以å\89\8dã\81®ã\83\90ã\83¼ã\82¸ã\83§ã\83³ã\81§ã\81¯ã\80\81<acronym>JDBC</acronym>ã\83\89ã\83©ã\82¤ã\83\90ã\81®"<literal>ApplicationName</literal>" ã\81¨ "<literal>assumeMinServerVersion=9.0</literal>"ã\82ªã\83\97ã\82·ã\83§ã\83³ã\82\92æ\8c\87å®\9aã\81\97ã\81¦ã\82\82ã\82¹ã\82¿ã\83¼ã\83\88ã\82¢ã\83\83ã\83\97ã\83\91ã\82±ã\83\83ã\83\88ã\81®ä¸ã\81«ã\82¢ã\83\97ã\83ªã\82±ã\83¼ã\82·ã\83§ã\83³å\90\8dã\82\92å\90«ã\81¿ã\81¾ã\81\9bã\82\93ã\80\82
<acronym>JDBC</acronym>から<xref linkend="guc-app-name-redirect-preference-list">機能を使用したければ、postgresql-9.4 以降のドライバをお使いください
</para>
</caution>
</term>
<listitem>
<para>
- Specifies the list of <replaceable>"database-name:node id"</replaceable> pairs
+ Specifies the list of <replaceable>"database-name:node id(ratio)"</replaceable> pairs
to send <acronym>SELECT</acronym> queries to a particular backend
- node for a particular database connection.
- For example, by specifying "test:1", <productname>Pgpool-II</productname>
- will redirect all <acronym>SELECT</acronym> queries to the backend node of ID 1 for
+ node for a particular database connection at a specified load balance ratio.
+ The load balance ratio specifies a value between 0 and 1. The default is 1.0.
+ </para>
+ <para>
+ For example, by specifying "test:1(0.5)", <productname>Pgpool-II</productname>
+ will redirect 50% <acronym>SELECT</acronym> queries to the backend node of ID 1 for
the connection to "test" database.
You can specify multiple <replaceable>"database name:node id"</replaceable> pair by separating them
using comma (,).
You can use special keywords as <replaceable>node id</replaceable>.
If <emphasis>"primary"</emphasis> is specified, queries are sent to the primary node, and
if <emphasis>"standby"</emphasis> is specified, one of the standby nodes are selected randomly
- based on weights.
+ based on weights (<xref linkend="guc-backend-weight">).
</para>
<example id="example-database-redirect-list">
</listitem>
<listitem>
<para>
- Route all <acronym>SELECT</acronym> queries on <literal>mydb0</literal> or on
- <literal>mydb1</literal> databases to backend node of ID 1.
+ Route 30% <acronym>SELECT</acronym> queries on <literal>mydb0</literal> or on
+ <literal>mydb1</literal> databases to backend node of ID.
+ The other 70% <acronym>SELECT</acronym> queries will be sent to other backend nodes.
</para>
</listitem>
<listitem>
<para>
then the <xref linkend="guc-database-redirect-preference-list"> will be configured as follows:
<programlisting>
-database_redirect_preference_list = 'postgres:primary,mydb[01]:1,mydb2:standby'
+database_redirect_preference_list = 'postgres:primary,mydb[01]:1(0.3),mydb2:standby'
</programlisting>
</para>
</example>
<listitem>
<para>
- Specifies the list of <replaceable>"application-name:node id"</replaceable> pairs
+ Specifies the list of <replaceable>"application-name:node id(ratio)"</replaceable> pairs
to send <acronym>SELECT</acronym> queries to a particular backend
- node for a particular client application connection.
+ node for a particular client application connection at a specified load balance ratio.
</para>
<note>
<para>
For example, application name of <command>psql</command> command is
- <literal>"psql"</literal>
+ <literal>"psql"</literal>.
</para>
<note>
thus you can also use the regular expressions for application names.
Similarly special keyword <emphasis>"primary"</emphasis> indicates the primary node and
<emphasis>"standby"</emphasis> indicates one of standby nodes.
+ The load balance weight specifies a value between 0 and 1. The default is 1.0.
</para>
<example id="example-app-name-redirect-list">
</listitem>
<listitem>
<para>
- Route all <acronym>SELECT</acronym> queries from <literal>myapp1</literal>
- client to backend node of ID 1.
+ Route 30% <acronym>SELECT</acronym> queries from <literal>myapp1</literal>
+ client to backend node of ID 1. The other 70% SELECT queries will be sent to other backend nodes.
</para>
</listitem>
<listitem>
<para>
then the <xref linkend="guc-app-name-redirect-preference-list"> will be configured as follows:
<programlisting>
-app_name_redirect_preference_list = 'psql:primary,myapp1:1,myapp2:standby'
+app_name_redirect_preference_list = 'psql:primary,myapp1:1(0.3),myapp2:standby'
</programlisting>
</para>
</example>
<xref linkend="guc-app-name-redirect-preference-list"> takes precedence
over the <xref linkend="guc-database-redirect-preference-list">.
</para>
+ <para>
+ For example, if you set
+ <literal>database_redirect_preference_list = 'postgres:standby(1.0)'</literal> and
+ <literal>app_name_redirect_preference_list = 'myapp1:primary(1.0)'</literal>,
+ all SELECT from application myapp1 on postgres database will be sent to primary backend node.
+ </para>
+ </note>
+
+ <note>
+ <para>
+ By specifying of <xref linkend="guc-app-name-redirect-preference-list"> and
+ <xref linkend="guc-database-redirect-preference-list">, when multiple database
+ names and application names are matched, the first setting will be used.
+ </para>
+ <para>
+ For example, if you set
+ <literal>database_redirect_preference_list = 'postgres:primary,postgres:standby'</literal>,
+ <literal>"postgres: primary"</literal> will be used.
+ </para>
</note>
<caution>
typedef struct {
char *left_token;
char *right_token;
+ double weight_token;
} Left_right_token;
typedef struct {
int selected_slot;
double total_weight,r;
int i;
- int index;
+ int index_db = -1, index_app = -1;
POOL_SESSION_CONTEXT *ses = pool_get_session_context(false);
int tmp;
+ int no_load_balance_node_id = -2;
/*
* -2 indicates there's no database_redirect_preference_list. -1 indicates
*/
int suggested_node_id = -2;
- /*
+#if defined(sun) || defined(__sun)
+ r = (((double)rand())/RAND_MAX);
+#else
+ r = (((double)random())/RAND_MAX);
+#endif
+
+ /*
* Check database_redirect_preference_list
*/
if (SL_MODE && pool_config->redirect_dbnames)
/* Check to see if the database matches any of
* database_redirect_preference_list
*/
- index = regex_array_match(pool_config->redirect_dbnames, database);
- if (index >= 0)
+ index_db = regex_array_match(pool_config->redirect_dbnames, database);
+ if (index_db >= 0)
{
/* Matches */
ereport(DEBUG1,
(errmsg("selecting load balance node db matched"),
- errdetail("dbname: %s index is %d dbnode is %s", database, index, pool_config->db_redirect_tokens->token[index].right_token)));
+ errdetail("dbname: %s index is %d dbnode is %s weight is %f", database, index_db,
+ pool_config->db_redirect_tokens->token[index_db].right_token,
+ pool_config->db_redirect_tokens->token[index_db].weight_token)));
- tmp = choose_db_node_id(pool_config->db_redirect_tokens->token[index].right_token);
+ tmp = choose_db_node_id(pool_config->db_redirect_tokens->token[index_db].right_token);
if (tmp == -1 || (tmp >= 0 && VALID_BACKEND(tmp)))
- {
suggested_node_id = tmp;
- }
}
}
- /*
+ /*
* Check app_name_redirect_preference_list
*/
if (SL_MODE && pool_config->redirect_app_names)
*/
if (app_name && strlen(app_name) > 0)
{
- /* Check to see if the aplication name matches any of
+ /*
+ * Check to see if the aplication name matches any of
* app_name_redirect_preference_list.
*/
- index = regex_array_match(pool_config->redirect_app_names, app_name);
- if (index >= 0)
+ index_app = regex_array_match(pool_config->redirect_app_names, app_name);
+ if (index_app >= 0)
{
+
+ /*
+ * if the aplication name matches any of app_name_redirect_preference_list,
+ * database_redirect_preference_list will be ignored.
+ */
+ index_db = -1;
+
/* Matches */
ereport(DEBUG1,
(errmsg("selecting load balance node db matched"),
- errdetail("app_name: %s index is %d dbnode is %s", app_name, index, pool_config->app_name_redirect_tokens->token[index].right_token)));
+ errdetail("app_name: %s index is %d dbnode is %s weight is %f", app_name, index_app,
+ pool_config->app_name_redirect_tokens->token[index_app].right_token,
+ pool_config->app_name_redirect_tokens->token[index_app].weight_token)));
- tmp = choose_db_node_id(pool_config->app_name_redirect_tokens->token[index].right_token);
+ tmp = choose_db_node_id(pool_config->app_name_redirect_tokens->token[index_app].right_token);
if (tmp == -1 || (tmp >= 0 && VALID_BACKEND(tmp)))
- {
suggested_node_id = tmp;
- }
}
}
}
if (suggested_node_id >= 0)
{
- ereport(DEBUG1,
- (errmsg("selecting load balance node"),
- errdetail("selected backend id is %d", suggested_node_id)));
+ /*
+ * 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.
+ */
+ if ((index_db >= 0 && r <= pool_config->db_redirect_tokens->token[index_db].weight_token) ||
+ (index_app >= 0 && r <= pool_config->app_name_redirect_tokens->token[index_app].weight_token))
+ {
+ ereport(DEBUG1,
+ (errmsg("selecting load balance node"),
+ errdetail("selected backend id is %d", suggested_node_id)));
+ return suggested_node_id;
+ }
+ else
+ no_load_balance_node_id = suggested_node_id;
+ }
- return suggested_node_id;
+ /* In case of sending to standby */
+ if (suggested_node_id == -1)
+ {
+ /* If the weight is less than random rate then send to primary. */
+ if ((index_db >= 0 && r > pool_config->db_redirect_tokens->token[index_db].weight_token) ||
+ (index_app >= 0 && r > pool_config->app_name_redirect_tokens->token[index_app].weight_token))
+ {
+ ereport(DEBUG1,
+ (errmsg("selecting load balance node"),
+ errdetail("selected backend id is %d", PRIMARY_NODE_ID)));
+ return PRIMARY_NODE_ID;
+ }
}
/* Choose a backend in random manner with weight */
{
if (VALID_BACKEND(i))
{
+ if (i == no_load_balance_node_id)
+ continue;
if (suggested_node_id == -1)
{
if (i != PRIMARY_NODE_ID)
total_weight = 0.0;
for (i=0;i<NUM_BACKENDS;i++)
{
- if (suggested_node_id == -1 && i == PRIMARY_NODE_ID)
+ if ((suggested_node_id == -1 && i == PRIMARY_NODE_ID) || i == no_load_balance_node_id)
continue;
if (VALID_BACKEND(i) && BACKEND_INFO(i).backend_weight > 0.0)
-SELECT 'test6'
+SELECT 'test11'
--- /dev/null
+SELECT 'test9'
source ./bashrc.ports
-echo "database_redirect_preference_list = 'postgres:primary,test:1,mydb[5-9]:2,test2:standby'" >> etc/pgpool.conf
+echo "database_redirect_preference_list = 'postgres:primary,test:1,mydb[5-9]:2,test2:standby,test3:primary(0.0),test4:standby(0.0),test5:primary(1.0)'" >> etc/pgpool.conf
./startall
$CREATEDB mydb6
$CREATEDB test2
+$CREATEDB test3
+$CREATEDB test4
+$CREATEDB test5
$PGBENCH -i postgres
ok=yes
# should be redirect to primary (node 0)
$PSQL -c "SELECT 'test1'" postgres
-test `getnode "test1"` -eq 0 || ok=ng
+test `getnode "'test1'"` -eq 0 || ok=ng
+echo $ok
# should be redirect to node 1
$PSQL -c "SELECT 'test2'" test
-test `getnode "test2"` -eq 1 || ok=ng
+test `getnode "'test2'"` -eq 1 || ok=ng
+echo $ok
# should be redirect to node 2
$PSQL -c "SELECT 'test3'" mydb6
-test `getnode "test3"` -eq 2 || ok=ng
+test `getnode "'test3'"` -eq 2 || ok=ng
+echo $ok
# should be redirect to either node 1 or 2
$PSQL -c "SELECT 'test4'" test2
-test `getnode "test4"` -eq 1 -o `getnode "test4"` -eq 2 || ok=ng
+test `getnode "'test4'"` -eq 1 -o `getnode "test4"` -eq 2 || ok=ng
+echo $ok
+
+# should be redirect to either node 1 or 2
+$PSQL -c "SELECT 'test5'" test3
+
+test `getnode "'test5'"` -eq 1 -o `getnode "test5"` -eq 2 || ok=ng
+echo $ok
+
+# should be redirect to primary (node 0)
+$PSQL -c "SELECT 'test6'" test4
+
+test `getnode "'test6'"` -eq 0 || ok=ng
+echo $ok
+
+# should be redirect to primary (node 0)
+$PSQL -c "SELECT 'test7'" test5
+
+test `getnode "'test7'"` -eq 0 || ok=ng
+
+echo $ok
echo "app_name_redirect_preference_list = 'psql:primary,pgbench:standby'" >> etc/pgpool.conf
wait_for_pgpool_startup
# should be redirect to node 0 because application name is psql
-$PSQL -c "SELECT 'test5'" mydb6
+$PSQL -c "SELECT 'test8'" mydb6
-test `getnode "test5"` -eq 0 || ok=ng
+test `getnode "'test8'"` -eq 0 || ok=ng
+echo $ok
# should be redirect to either node 1 or 2
$PGBENCH -t 1 -f ../select.pgbench postgres
-test `getnode "test6"` -eq 1 -o `getnode "test6"` -eq 2 || ok=ng
+test `getnode "'test9'"` -eq 1 -o `getnode "test9"` -eq 2 || ok=ng
+echo $ok
+
+
+echo "app_name_redirect_preference_list = 'psql:primary(0.0),pgbench:standby(1.0)'" >> etc/pgpool.conf
+
+./pgpool_reload
+sleep 1
+
+wait_for_pgpool_startup
+
+# should be redirect to either node 1 or 2
+$PSQL -c "SELECT 'test10'" mydb6
+
+test `getnode "'test10'"` -eq 1 -o `getnode "test10"` -eq 2 || ok=ng
+echo $ok
+
+# should be redirect to either node 1 or 2
+$PGBENCH -t 1 -f ../select1.pgbench postgres
+
+test `getnode "'test11'"` -eq 1 -o `getnode "test11"` -eq 2 || ok=ng
+echo $ok
./shutdownall
int len;
char *left_token;
char *right_token;
+ char *weight_token = NULL;
int i,j;
len = strlen(token)+1;
left_token = palloc(len);
right_token = palloc(len);
+ weight_token = palloc(len);
for (i=0;token[i] && token[i] != delimi2;i++)
left_token[i] = token[i];
i++;
j = 0;
- for (;token[i];i++)
+ for (;token[i] && token[i] != '('; i++)
right_token[j++] = token[i];
right_token[j] = '\0';
+ /* delimiter 3 */
+ int k = 0;
+ if (token[i] == '(')
+ {
+ i++;
+ for (;token[i] && token[i] != ')'; i++)
+ weight_token[k++] = token[i];
+ }
+ weight_token[k] = '\0';
+
if (lrtokens->pos == lrtokens->size)
{
lrtokens->size += AR_ALLOC_UNIT;
}
lrtokens->token[lrtokens->pos].left_token = left_token;
lrtokens->token[lrtokens->pos].right_token = right_token;
+ if (weight_token[0] != '\0')
+ lrtokens->token[lrtokens->pos].weight_token = atof(weight_token);
+ else
+ lrtokens->token[lrtokens->pos].weight_token = 1.0;
+
lrtokens->pos++;
}
pfree(mystr);