9.4 设置复制和负载均衡
要配置pgpool,我们可以简单地使用一个包含一种典型的配置信息的已经存在的样本文件,将它拷贝到我们的配置目录并修改之:
$ cp /usr/local/etc/pgpool.conf.sample /usr/local/etc/pgpool.conf
改写这个配置文件比从头写这个文件要容易的多。在下面的列表中,您将看到一个实例配置,您可以把它用于两个节点的简单配置:
listen_addresses = 'localhost'
port = 9999
socket_dir = '/tmp'
pcp_port = 9898
pcp_socket_dir = '/tmp'
backend_hostname0 = 'localhost'
backend_port0 = 5432
backend_weight0 = 1
backend_data_directory0 = '/home/hs/db'
backend_flag0 = 'ALLOW_TO_FAILOVER'
backend_hostname1 = 'localhost'
backend_port1 = 5433
backend_weight1 = 1
backend_data_directory1 = '/home/hs/db2'
backend_flag1 = 'ALLOW_TO_FAILOVER'
enable_pool_hba = off
pool_passwd = 'pool_passwd'
authentication_timeout = 60
ssl = off
num_init_children = 32
max_pool = 4
child_life_time = 300
child_max_connections = 0
connection_life_time = 0
client_idle_limit = 0
connection_cache = on
reset_query_list = 'ABORT; DISCARD ALL'
replication_mode = on
replicate_select = off
insert_lock = on
load_balance_mode = on
ignore_leading_white_space = on
white_function_list = ''
black_function_list = 'nextval,setval'
现在让我们来详细讨论这些设置,看看每个设置的意义:
• pid_file_name: 就像大多数软件组件一样,pgpool会写一个PID文件。我们可以精确地定义这个文件的位置。通常PID文件处于/var/目录下面。
• listen_addresses: 这个设置和PostgreSQL的listen_address设置一样。这里的想法是这个设置定义监听哪些IP地址。
• port: 这个设置定义了哪个系统上的TCP端口将会被监听。
• socket_dir: 没有使用TCP端口的硬性要求。UNIX套接字也是可以的。socket_dir将定义这些UNIX套接字存放在哪里。
• pcp_port: 管理界面将会监听哪个TCP端口。
• pcp_socket_dir: 管理界面将会使用的UNIX套接字目录。
• backend_hostname0:在我们的设置中的第一个数据库主机名。
• backend_port0:该系统的TCP端口。
• backend_weight0:在pgpool中,我们可以设置独立节点的权重。权重较高的节点将会自动确保较多的请求会发送到该节点。
• backend_data_directory0: 属于该实例的PGDATA目录。
• backend_flag:这个设置告诉pgpool是否一个节点允许故障转移。
允许两个设置: ALLOW_TO_FAILOVER 和 DISALLOW_TO_FAILOVER。
• enable_pool_hba:如果该设置为true,pgpool将使用pool_hba.conf进行身份验证。这里pgpool遵循PostgreSQL相同的概念。
• pool_passwd: pgpool的密码文件。
• authentication_timeout: 为连接池身份验证定义超时时间。
• ssl: 如果该设置被设置为true,客户端和后端连接将启动SSL。
• num_init_children: 当pgpool启动时,一些连接将被预先分配出来,确保响应时间保持在低水平。该设置将定义初始子进程的数目。默认值为32。
• max_pool: 该设置定义了每个连接池尺寸的最大值。
请注意,从pgpool进程到后端的连接数可能达到num_init_children * max_pool。该参数只能在服务器启动是设置。
• child_life_time: 这里定义了允许一个子进程在它被终止之前所允许的秒数。
• child_max_connections: 这个数目的连接连到相同的子进程之后,它将被终止。换而言之,一个进程在它被回收在利用之前,它将处理如此多的连接。
• connection_life_time: 这会告诉您在一个连接被回收利用之前,它将存活多久。
• client_idle_limit: 如果一个子进程已经闲置了这么长的时间,它将断开以客户端。
• connection_cache: 如果该设置为true,到(存储)后端的连接将被缓存。
• reset_query_list: 这里定义了一个命令行列表,当一个客户端推出一个会话是,它必须被执行。它用于清理一个连接。
• replication_mode: 这将明确地打开复制,默认值为false。
• replicate_select: 我们是否应该复制SELECT语句?
• insert_lock:当复制有关联(数据类型序列)的表时,pgpool必须确保这些数据保持同步。
• load_balance_mode: pgpool是否该把负载分割到系统中的所有主机上?默认值为false。
• ignore_leading_white_space: 以空白开始的查询是否该被忽略?
• white_function_list: 当pgpool运行一个存储过程,pgpool不知道它实际在做什么。SELECT func() 可以是读操作或者写操作—没有办法从外部知道实际会发生什么。white_function_list允许您教pgpool哪些函数可以安全地进行负载均衡。如果一个函数写入数据,它一定不是负载均衡的,否则数据将不会同步到这些服务器上。不同步一定节省了任何开销。
• black_function_list: 这与white_function_list相反。它会告诉 pgpool 哪些函数必须被复制,以确保事情保持同步。
请记住,在max_pool和pgpool的子进程之间有一个重要的关系。单个子进程可以处理max_pool个连接。
9.4.1 密码认证
一旦您完成了一个pgpool配置文件,我们就可以进一步配置身份验证。在我们的例子中,我们想添加一个叫 hs 的用户。hs的密码仅仅是hs。pool_passwd将负责存储密码。该文件的格式很简单:它将保存用户的名字,冒号,和MD5加密的密码。
要加密一个密码,我们可以使用pg_md5脚本:
$ pg_md5 hs
789406d01073ca1782d86293dcfc0764
然后,我们可以把所有这些东西添加到存储用户和密码的配置文件。在pgpool的例子中,这个文件是pcp.conf:
# USERID:MD5PASSWD
hs:789406d01073ca1782d86293dcfc0764
9.4.2 启动pgpool和测试设置
既然我们已经把所有的组件都放到了各自的位置,我们可以启动pgpool了:
$ pgpool –f /usr/local/pgpool/pgpool.conf
如果没有错误,我们应该看到几等待来自客户端的工作的个进程在那里:
$ ps ax | grep pool
30927 pts/4 S+ 0:00 pgpool -n
30928 pts/4 S+ 0:00 pgpool: wait for connection request
30929 pts/4 S+ 0:00 pgpool: wait for connection request
30930 pts/4 S+ 0:00 pgpool: wait for connection request
30931 pts/4 S+ 0:00 pgpool: wait for connection request
30932 pts/4 S+ 0:00 pgpool: wait for connection request
正如您可以清晰地看到,pgpool将在进程表中显示几个进程。
9.4.3 连接主机
基本上,我们已经可以连接到pgpool,并执行查询—但是,这将会立即导致灾难和不一致。在我们继续执行一些实际的操作之前,我们应该检查一下集群中所有节点的状态。要这样做,我们可以使用一个叫做pcp_node_info 的工具:
$ pcp_node_info 5 localhost 9898 hs hs 0
localhost 5432 3 0.500000
$ pcp_node_info 5 localhost 9898 hs hs 1
localhost 5433 2 0.500000
如果这是您第一次看到它,这种调用pcp_node_info的格式有点复杂并且不容易阅读。
请注意,这里权重都是0.5。在配置中,我们已经设置了两个后端的权重都为1。pgpool已经自动调整 了权重,以便它们相加结果为1。
这里是 pcp_node_info 的语法:
pcp_node_info - display a pgpool-II node's information
Usage: pcp_node_info [-d] timeout hostname port# username password nodeID
-d, --debug : enable debug message (optional)
timeout : connection timeout value in seconds.
command exits on timeout
hostname : pgpool-II hostname
port# : PCP port number
username : username for PCP authentication
password : password for PCP authentication
nodeID : ID of a node to get information for
Usage: pcp_node_info [options]
Options available are:
-h, --help : print this help
-v, --verbose : display one line per information
with a header
第一个参数是timeout。它将定义一个请求的最大时间。然后我们知道那个主机和PCP端口基础设施。最后,我们通过用户名和密码,以及我们想要的信息的主机的数量。该系统将响应主机名,端口,状态和节点的权重。在我们的例子中,我们必须把注意力集中到状态列。它可以返回四个不同的值。
• 0: 这个状态只在初始化时使用。PCP永远都不会显示它。
• 1: 节点运行。但没有连接。
• 2: 节点运行。连接在连接池中。
• 3: 节点关闭。
在我们的例子中,我们可以看到节点1基本上返回状态3—它是关机的。这显然是一个问题,如果我们现在执行写操作。它不会在两个节点结束,而是只在它们中的一个节点结束。
要解决这个问题,我们可以调用 pcp_attach_node并使节点工作:
$ pcp_attach_node 5 localhost 9898 hs hs 0
$ pcp_node_info 5 localhost 9898 hs hs 0
localhost 5432 1 0.500000
一旦我们增加了节点,我们可以 再次检查它的状态。它的状态将是开机并运行。
为了测试我们的设置,我们可以检查psql并显示系统中的数据库列表:
$ psql -l -p 9999
List of databases
Name | Owner | Encoding | Collate | Ctype ...
----------+-------+-----------+-------------+-- ...
postgres | hs | SQL_ASCII | en_US.UTF-8 | C ...
template0 | hs | SQL_ASCII | en_US.UTF-8 | C ...
template1 | hs | SQL_ASCII | en_US.UTF-8 | C ...
(3 rows)
答案和我们预期的议案。我们可以看到一个空的数据库实例。