使用PgBouncer连接池

使用PgBouncer连接池

PgBouncer工具管理用于PostgreSQL和Greenplum数据库连接的连接池。

Greenplum数据库安装包括PgBouncer连接池软件。下列主题描述了如何对Greenplum数据库设置和使用PgBouncer。有关如何把PgBouncer和PostgreSQL一起使用请见 PgBouncer网站

另外,PgBouncer的参考信息可见Greenplum数据库工具指南

概述

数据库连接池是一种数据库连接的缓存。一旦一个池子的连接被建立,连接池就能消除创建数据库连接的开销,这样客户端能更快地连接并且服务器的负载也能被降低。

PgBouncer连接池来自于PostgreSQL社区,它被包括在Greenplum数据库中。PgBouncer可以为多个数据库管理连接池,并且这些数据库可以位于不同的Greenplum数据库集群或者PostgreSQL后端。PgBouncer会为每一种数据库用户与数据库的组合建立一个池。一个被池化的连接只能被来自于同一个用户和数据库的另一个连接请求重用。

客户端应用不需要做软件修改,但是要连接到连接池的主机和端口而不是Greenplum的Master主机和端口。PgBouncer会创建新的数据库连接或者重用一个已有的连接。当客户端断开连接时,该连接会被返回给连接池以备重用。

PgBouncer支持PostgreSQL和Greenplum数据库所共享的标准连接接口。一个请求数据库连接的客户端会提供PgBouncer所在的主机名及端口,还有数据库名、用户名和口令。PgBouncer在其配置文件中查找所请求的数据库(可能是真实数据库的一个别名)为数据库连接找到主机名、端口和数据库名。配置文件条目还决定如何认证用户以及将使用哪个数据库角色,一个“强制用户”可以覆盖客户端连接请求所提供的用户名。

PgBouncer要求一个认证文件,它是一个包含了用户和口令列表的文本文件。口令可能是明文、被MD5编码过或者一个LDAP/AD查找串。用户也可以设置PgBouncer为不在认证文件中的用户查询目标数据库。

PgBouncer有三种池模式来共享连接:
  • 会话池化 – 当一个客户端连接时,只要它保持连接状态,就分配给它一个连接。当该客户端断开连接时,该连接才被放回到池中。
  • 事务池化 – 在一个事务运行期间,分配一个连接给客户端。当PgBouncer发现事务完成,该连接就被放回到池中。这种模式只能被用于不使用依赖于会话的特性的应用。
  • 语句池化 – 语句池化类似于事务池化,但是不允许多语句事务。这种模式的目标是为了在客户端强制自动提交模式,且它的定位是PostgreSQL上的PL/Proxy。

可以为PgBouncer设置一种默认的池模式,并且该模式可以被单个数据库和用户覆盖。

通过连接到一个虚拟的pgbouncer数据库,用户可以使用类SQL命令监控和管理PgBouncer。可以不重启PgBouncer就修改配置参数,只需要重新载入配置文件就能发现更改。

PgBouncer还不支持SSL连接。如果用户想要加密客户端和PgBouncer之间的通信,用户可以使用stunnel,它是一种使用OpenSSL加密库创建TLS加密隧道的免费软件工具。方法请见用stunnel保护PgBouncer

配置和启动PgBouncer

PgBouncer可以被运行在Greenplum数据库的Master上或者另一台服务器上。如果用户把PgBouncer安装在一台单独的服务器上,用户可以通过更新PgBouncer配置文件并且用PgBouncer管理控制台重载该配置来轻易地把客户端切换到后备Master上。

设置PgBouncer的步骤如下。

  1. 创建一个PgBouncer配置文件,例如pgbouncer.ini。 这里是一个简单的配置文件:
    [databases]
    postgres = host=127.0.0.1 port=5432 dbname=postgres
    mydb = host=127.0.0.1 port=5432 dbname=mydb
    
    [pgbouncer]
    pool_mode = session
    listen_port = 6543
    listen_addr = 127.0.0.1
    auth_type = md5
    auth_file = users.txt
    logfile = pgbouncer.log
    pidfile = pgbouncer.pid
    admin_users = gpadmin

    该文件是.ini文件格式并且有三个小节: databasespgbouncerusers。databases小节列出了数据库及其连接细节。pgbouncer小节配置了PgBouncer实例。

  2. 创建一个认证文件。该文件的名称必须匹配pgbouncer.ini文件中的 auth_file参数,在这个例子中是 users.txt。每一行包含一个用户名和口令。口令串的格式匹配PgBouncer配置文件中的auth_type参数。如果auth_type参数是plain,口令串就是一个明文口令,例如:
    "gpadmin" "gpadmin1234"
    下面例子中的auth_typemd5,因此认证域必须被MD5编码。被MD5编码的口令格式是:
    "md5" + MD5(<password><username>)
    用户可以使用Linux的md5sum命令来计算MD5串。例如,如果gpadmin的口令是admin1234,下面的命令会打印用于口令域的字符串:
    $ user=gpadmin; passwd=admin1234; echo -n md5; echo $passwd$user | md5sum
    md53ce96652dedd8226c498e09ae2d26220

    这里是PgBouncer认证文件中用于gpadmin用户的MD5编码过的条目:

    "gpadmin" "md53ce96652dedd8226c498e09ae2d26220"

    要用LDAP或者活动目录服务器认证用户,口令域应该包含一个LDAP查找串。例如:

    "gpdbuser1" "ldap://10.0.0.11:10389/uid=gpdbuser1,ou=users,ou=system"
    对于活动目录,一个用户条目看起来像这个例子:
    "gpdbuser2" "ldap://10.0.0.12:389/gpdbuser2"
    配置PgBouncer用LDAP服务器认证用户的步骤请见对PgBouncer设置LDAP认证

    关于认证文件的细节,请见Greenplum数据库工具指南中PgBouncer参考的“认证文件格式”小节。

  3. 启动 pgbouncer:
    $ $GPHOME/bin/pgbouncer -d pgbouncer.ini

    -d or --daemon选项会让PgBouncer作为一个后台进程运行。pgbouncer命令的语法及其选项请见Greenplum数据库工具指南中的PgBouncer参考。

  4. 更新客户端应用,让它们连接到pgbouncer而不是直接连接到Greenplum数据库服务器。要启动psql,例如:
    $ psql -p 6543 -U someuser postgres

服务器重置查询

当一个连接被返回给连接池时,它必须被重置为刚创建的连接的状态。在把一个连接返回给连接池之前,PgBouncer通过发出一个查询来实现这种重置。PostgreSQL 8.3及其后的版本有一个用于此种目的的DISCARD ALL命令,它标准PgBouncer发布的默认重置查询。Greenplum数据库不支持DISCARD ALL,如果使用该命令会出现错误。

可以在PgBouncer配置文件的server_reset_query参数中指定重置查询。对于PgBouncer处于会话池化模式的Greenplum数据库,server_reset_query参数可以被设置为这个查询:
RESET ALL; SET SESSION AUTHORIZATION DEFAULT

这是Greenplum数据库 4.7.0及其后版本包括的PgBouncer修改版中的默认服务器重置查询。尽管它与PgBouncer原生的不同,它也能确保连接池对于Greenplum数据库用户透明并且客户端应用不需要为了使用连接池而被修改。

更多有关PgBouncer配置文件的server_reset_query参数的信息,请见Greenplum数据库工具指南中的PgBouncer参考。

管理PgBouncer

PgBouncer有一个管理控制台,可以登录到pgbouncer虚拟数据库来访问它。该控制台接受类SQL命令,这些命令允许用户监控、重新配置和管理PgBouncer。

要开始使用PgBouncer管理控制台,请遵循下列步骤。

  1. psql登录到pgbouncer虚拟数据库:
    $ psql -p 6543 -U username pgbouncer

    用户名必须是pgbouncer.ini配置文件中admin_users参数中所设置的值。如果pgbouncer进程运行在用户登录的当前Unix用户的UID下,用户还可以用该用户名登录。

  2. 要看可用的命令,可运行show help命令:
    pgbouncer=# show help;
    NOTICE:  Console usage
    DETAIL:
           SHOW HELP|CONFIG|DATABASES|POOLS|CLIENTS|SERVERS|VERSION
    	SHOW STATS|FDS|SOCKETS|ACTIVE_SOCKETS|LISTS|MEM
    	SHOW DNS_HOSTS|DNS_ZONES
    	SET key = arg
    	RELOAD
    	PAUSE [<db>]
    	RESUME [<db>]
    	DISABLE <db>
    	ENABLE <db>
    	KILL <db>
    	SUSPEND
    	SHUTDOWN
  3. 如果用户对pgbouncer.ini文件做了修改,用户可以用 RELOAD命令重载它:
    pgbouncer=# RELOAD;

要把客户端映射到服务器连接,可使用SHOW CLIENTSSHOW SERVERS视图:

  1. 使用ptrlink把本地客户端连接映射到服务器连接。
  2. 使用客户端连接的addrport标识来自客户端的TCP连接。
  3. 使用local_addrlocal_port标识到服务器的TCP连接。

所有管理控制台命令的完整文档,请见Greenplum数据库工具指南中PgBouncer参考的“PgBouncer管理控制台命令”。

升级PgBouncer

用户可以在不丢掉连接的情况下升级PgBouncer。只需要用-R选项和相同的配置文件启动一个新的PgBouncer进程:

$ pgbouncer -R -d config.ini

-R(重启)选项导致这个新进程通过一个Unix套接字连接到旧进程的控制台并且发出下列命令:

SUSPEND;
SHOW FDS;
SHUTDOWN;

当新进程看到旧进程已经消失,它会使用旧的连接继续工作。这是可能的,因为SHOW FDS命令会把真实的文件描述符发送给新进程。如果这种传送由于任何原因失败,可杀死新进程让旧进程继续。

对PgBouncer设置LDAP认证

在使用PgBouncer连接池时,用户可以用LDAP或者活动目录服务来认证Greenplum数据库用户。在使用LDAP认证时,用户可以通过设置stunnel来保护客户端连接(见用stunnel保护PgBouncer连接

在开始之前,用户必须有一台LDAP或者活动目录服务器以及一个Greenplum数据库集群。
  1. 在LDAP/AD服务器中创建Greenplum数据库用户,例如 gpdbuser1gpdbuser2
  2. 在数据库中创建相应的Greenplum数据库用户:
    createuser gpdbuser1
    createuser gpdbuser2
  3. 把这些用户加到Greenplum数据库的pg_hba.conf文件中:
    host     all         gpdbuser1              0.0.0.0/0     trust
    host     all         gpdbuser2              0.0.0.0/0     trust
    
  4. 用下面的内容创建一个PgBouncer的config.ini文件:
    [databases]
    * = host=GPDB_host_addr port=GPDB_port
    
    [pgbouncer]
    listen_port = 6432
    listen_addr = 0.0.0.0
    auth_type = plain
    auth_file = users.txt
    logfile = pgbouncer.log
    pidfile = pgbouncer.pid
    ignore_startup_parameters=options
    
  5. 创建users.txt PgBouncer认证文件。第一个域是用户名而第二个域是用于搜索该用户的LDAP或者活动目录查找串。例如,对于OpenLDAP或者ApacheDS, users.txt中的一个用户条目看起来是这样:
    "gpdbuser1" "ldap://10.0.0.11:10389/uid=gpdbuser1,ou=users,ou=system"
    对于活动目录,一个用户条目看起来是这样:
    "gpdbuser1" "ldap://10.0.0.12:389/gpdbuser1"
  6. 用用户创建的config.ini文件启动PgBouncer:
    $ pgbouncer -d config.ini

用stunnel保护PgBouncer连接

PgBouncer没有SSL支持,因此数据库客户端和PgBouncer之间的连接是没有被加密的。要加密这些连接,用户可以使用stunnel,它是一种免费软件工具。stunnel是一种使用OpenSSL加密库把TLS加密加到网络服务的代理。较新版本的stunnel支持PostgreSQL的libpq协议,因此Greenplum和PostgreSQL客户端可以使用libpq的SSL支持安全地通过网络连接到作为PgBouncer代理设置的stunnel实例。如果用户使用的stunnel版本没有libpq支持,用户需要在客户端和PgBouncer主机两端都设置一个stunnel实例,这样才能在网络上创建一个安全的隧道。

在大部分平台上,用户都可以用系统的包管理器安装stunnel。对于Windows,用户可以从 https://www.stunnel.org/index.html下载一个安装器。如果没有打包好的版本可用,或者想要升级到新的版本,或者想要升级到一个新的OpenSSL版本,用户也可以下载源代码来安装stunnel。下一节提供了下载、编译和安装OpenSSL及stunnel的步骤。

完整的stunnel文档请访问stunnel documentation网站。

从源码安装stunnel

stunnel要求一个版本大于1.0的OpenSSL开发包。下面的指令会为Red Hat或者CentOS下载并且编译OpenSSL和stunnel。记得检查https://www.stunnel.org/index.htmlhttp://openssl.org来获得最新的版本。

  1. PREFIX环境变量设置为想要安装stunnel的目录,例如/usr/local/stunnel或者 /home/gpadmin/stunnel。如果用户选择在一个系统目录中安装stunnel,用户可能需要以root运行make install命令。
    export PREFIX=/path/to/install_stunnel
  2. 下面的命令会下载、编译并且安装版本1.0.2c的OpenSSL:
    wget ftp://ftp.openssl.org/source/openssl-1.0.2c.tar.gz
    tar xzf openssl-1.0.2c.tar.gz
    cd openssl-1.0.2c
    ./Configure linux-x86_64 --prefix=$PREFIX shared no-asm
    make
    make install_sw
    cd ..
  3. 用下列命令下载、编译并且安装stunnel:
    wget --no-check-certificate https://www.stunnel.org/downloads/stunnel-5.22.tar.gz
    tar xzf stunnel-5.22.tar.gz
    cd stunnel-5.22
    LDFLAGS="-Wl,-rpath,'"'$$'"ORIGIN/../lib'"
    ./configure --prefix=$PREFIX --with-ssl=$PREFIX
    make
    make install

为PgBouncer设置stunnel

为PgBouncer设置一个stunnel实例作为代理。该stunnel实例在它自己的端口上接受来自于数据库客户端的安全连接,解密包并且把它们转给同一主机(或者在受保护的本地网络中的另一台主机)上的PgBouncer实例。PgBouncer的结果(包括PgBouncer所管理的连接的数据库结果)会被加密并且通过网络返回给客户端。

  1. 在运行PgBouncer的服务器上,为stunnel配置文件创建一个目录,例如/home/gpadmin/stunnel
  2. 创建用于认证的证书和密钥文件。用户还可以使用一个现有的证书和密钥,或者用下列 openssl命令创建一对新的:
    $ openssl req -new -x509 -days 3650 -nodes -out stunnel.pem -keyout stunnel.key

    把文件stunnel.keystunnel.pem移动到用户的stunnel配置目录中。

  3. 用下列内容创建一个stunnel配置文件(例如stunnel.conf):
    debug = info
    socket = l:TCP_NODELAY=1
    socket = r:TCP_NODELAY=1
    
    debug = 7
    
    cert = /PATH/TO/stunnel.pem
    key = /PATH/TO/stunnel.key
    
    [pg-server]
    client=no
    accept = 0.0.0.0:5433             # 这是SSL监听端口
    connect = PGHOST:PGPORT   # 这是PgBouncer监听端口
    protocol = pgsql
    

    额外的配置选项请见 stunnel配置文件参考

  4. 在服务器上运行stunnel
    stunnel /path/to/stunnel-srv.conf
  5. 在客户端上,连接到其上的stunnel以及接受端口。例如:
    psql -h pgbouncer-host -p stunnel-accept-port database-name