【问题标题】:Can't use PGPool with Amazon RDS Postgres无法将 PGPool 与 Amazon RDS Postgres 一起使用
【发布时间】:2017-03-18 09:04:18
【问题描述】:

我有一个多可用区的 Postgres 9.4 RDS 实例,并且有一个从属只读副本。

到目前为止,负载平衡是在我的应用程序的业务层进行的,但效率低下,我希望使用 PGPool,因此应用程序与单个 Postgres 连接进行交互。

事实证明,使用 PGPool 一直很痛苦。如果我将其设置为负载均衡器,简单的 SELECT 查询会引发如下错误:

 SQLSTATE[HY000]: General error: 7 
 message contents do not agree with length in message type "N" 
 server sent data ("D" message) 
 without prior row description ("T" message)

如果我将它设置为使用流复制以主/从模式运行(如suggested in Postgres mail list),我会得到:

psql: ERROR:  MD5 authentication is unsupported 
in replication and master-slave modes.
HINT:  check pg_hba.conf

是的,好吧,pg_hba.conf 如果在 RDS 中失手,所以我无法更改它。

有没有人让 PGPool 在 RDS 中工作?是否有其他工具可以充当中间件来利用 RDS 中的读取副本?

【问题讨论】:

    标签: postgresql amazon-web-services rds pgpool


    【解决方案1】:

    我能够让它工作这里是我的工作配置文件:

    您必须使用 md5 身份验证,并将用户名/密码从数据库同步到 pool_passwd 文件。还需要开启 enable_pool_hba、load_balance_mode 和 master_slave_mode。

    pgpool.conf

    listen_addresses = '*'
    port = 9999
    pcp_listen_addresses = '*'
    pcp_port = 9898
    pcp_socket_dir = '/tmp'
    listen_backlog_multiplier = 1
    backend_hostname0 = 'master-rds-database-with-multi-AZ.us-west-2.rds.amazonaws.com'
    backend_port0 = 5432
    backend_weight0 = 0
    backend_flag0 = 'ALWAYS_MASTER'
    backend_hostname1 = 'readonly-replica.us-west-2.rds.amazonaws.com'
    backend_port1 = 5432
    backend_weight1 = 999
    backend_flag1 = 'ALWAYS_MASTER'
    enable_pool_hba = on
    pool_passwd = 'pool_passwd'
    ssl = on
    num_init_children = 1
    max_pool = 2
    connection_cache = off
    replication_mode = off
    load_balance_mode = on
    master_slave_mode = on
    

    pool_hba.conf

    local   all         all                               md5
    host    all         all         127.0.0.1/32          md5
    

    pool_passwd

    username:md5d51c9a7e9353746a6020f9602d452929
    

    要更新 pool_password,您可以使用 pg_md5

    echo username:md5`echo -n usernamepassword | md5sum`
    username:md5d51c9a7e9353746a6020f9602d452929 -
    

    运行示例的输出:

    psql --dbname=database --host=localhost --username=username --port=9999
    
    database=> SHOW POOL_NODES;
    
     node_id |                        hostname                 | port | status | lb_weight |  role   | select_cnt | load_balance_node | replication_delay
    ---------+-------------------------------------------------+------+--------+-----------+---------+------------+-------------------+-------------------
     0       | master-rds-database.us-west-2.rds.amazonaws.com | 8193 | up     | 0.000000  | primary | 0          | false             | 0
     1       | readonly-replica.us-west-2.rds.amazonaws.com    | 8193 | up     | 1.000000  | standby | 0          | true              | 0
    
    database=> select now();
    
     node_id |                        hostname                 | port | status | lb_weight |  role   | select_cnt | load_balance_node | replication_delay
    ---------+-------------------------------------------------+------+--------+-----------+---------+------------+-------------------+-------------------
     0       | master-rds-database.us-west-2.rds.amazonaws.com | 8193 | up     | 0.000000  | primary | 0          | false             | 0
     1       | readonly-replica.us-west-2.rds.amazonaws.com    | 8193 | up     | 1.000000  | standby | 1          | true              | 1
    
    database=> CREATE TABLE IF NOT EXISTS tmp_test_read_write ( data varchar(40) );
    CREATE TABLE
    database=> INSERT INTO tmp_test_read_write (data) VALUES (concat('',inet_server_addr()));
    INSERT 0 1
    database=> select data as master_ip,inet_server_addr() as replica_ip from tmp_test_read_write;
      master_ip   |  replica_ip
    --------------+---------------
     172.31.37.69 | 172.31.20.121
    (1 row)
    

    您还可以从日志中看到两个数据库的 id:

    2018-10-16 07:56:37: pid 124528: LOG:  DB node id: 0 backend pid: 21731 statement: CREATE TABLE IF NOT EXISTS tmp_test_read_write ( data varchar(40) );
    2018-10-16 07:56:47: pid 124528: LOG:  DB node id: 0 backend pid: 21731 statement: INSERT INTO tmp_test_read_write (data) VALUES (concat('',inet_server_addr()));
    2018-10-16 07:56:52: pid 124528: LOG:  DB node id: 1 backend pid: 24890 statement: select data as master_ip,inet_server_addr() as replica_ip from tmp_test_read_write;
    

    注意insert使用了master的ip_address,next select使用了只读replica的ip_address。

    我可以在更多测试后更新,但 psql 客户端测试看起来很有希望。

    【讨论】:

    • 不错。有点复杂,但还是不错的。所以,你告诉 pgpool 不要复制 bc 那是 RDS 的工作。您将副本视为主服务器。但是,相对权重似乎表明读取总是转到副本...您如何防止副本上的写入尝试?
    【解决方案2】:

    有 Citus(pgShard) 应该与标准 Amazon RDS 实例一起使用。它虽然有问题。如果您使用开源版本,您将遇到单点故障。它的协调节点不重复。

    您可以获得完全高可用性无缝故障转移版本,但您必须购买企业许可证,但它非常昂贵。每年的花费很容易达到 50,000 到 100,000 美元或更多。

    而且他们现在真的在推他们的云版本,这更加昂贵。

    https://www.citusdata.com/

    我还听说有人使用 HAProxy 在 Postgres 或 MySql 节点之间进行平衡。

    【讨论】:

    • 谢谢!我没听说过。
    • 来自 Citus 的 Ozgun -- 我想附上两个简短的笔记。在定价方面,我们的云版和企业版均按节点每月定价。云版本还包括硬件成本,小型集群的起价为 990 美元/月。在协调器节点成为单点故障(在社区版中),这是我们鼓励用户使用云的原因之一。在 Citus Cloud 中,我们可以自动fail over to the replica and attach the elastic IP to the replica
    • 没错。每个节点每月 900 美元以上,即使只有 10 个节点,每年也远远超过 100,000 美元。我被引用的云定价是这个价格的两倍多。而云服务根本没有意义。通过 Internet 到第三方数据中心访问数据库会为每个数据库写入和读取增加两个数量级的延迟。
    • @BrianC 如果我想连接到 AWS RDS,我应该使用“pg”而不是“pg-pool”吗?顺便说一句,我正在使用 pg-pool 和 Elephantsql,它工作得很好
    • 除非事情发生了变化,否则您不能将 pg-pool 与 AWS RDS 一起使用,因为您需要直接访问您在 AWS 的默认 Postgres RDS 服务中没有的 Postgres 配置文件。
    猜你喜欢
    • 2012-03-12
    • 2018-09-21
    • 2012-03-18
    • 2018-10-08
    • 2014-01-18
    • 1970-01-01
    • 2020-06-05
    • 1970-01-01
    相关资源
    最近更新 更多