如何优化Postgresql max_connections和node-postgres连接池?

时间:2016-10-31 17:29:55

标签: node.js postgresql api aws-rds node-postgres

简而言之,我无法通过利用Postgresql,Node.js和node-postgres的数据API每分钟支持超过5000个读取请求。瓶颈似乎介于API和DB之间。以下是详细信息。

我正在为Node.js支持的数据API使用AWS Postgresql RDS数据库实例(m4.4xlarge - 64 GB内存,16个vCPU,350 GB SSD,没有预配置IOPS)。默认情况下,RDS的max_connections = 5000。节点API在两个集群之间进行负载平衡,每个集群有4个进程(2个Ec2,其中4个vCPU运行API,集群模式下为PM2)。我使用node-postgres将API绑定到Postgresql RDS,并尝试使用它的连接池功能。以下是我的连接池代码示例:

var pool = new Pool({
    user: settings.database.username,
    password: settings.database.password,
    host: settings.database.readServer,
    database: settings.database.database,
    max: 25, 
    idleTimeoutMillis: 1000
});

/* Example of pool usage */
pool.query('SELECT my_column FROM my_table', function(err, result){

    /* Callback code here */
});

使用此实现并使用负载测试器进行测试,我可以在一分钟内支持大约5000个请求,平均响应时间约为190毫秒(这是我所期望的)。一旦我每分钟发出超过5000个请求,我的响应时间在最好的情况下会增加到超过1200毫秒,在最糟糕的情况下,API开始经常超时。监控表明对于运行Node.js API的EC2,CPU利用率仍低于10%。因此,我的重点是数据库和API与数据库的绑定。

我试图增加(并减少)node-postgres“max”连接设置,但API响应/超时行为没有变化。我也尝试过在RDS上配置IOPS,但没有改进。另外,有趣的是,我将RDS扩展到m4.10xlarge(160 GB内存,40个vCPU),虽然RDS CPU利用率大幅下降,但API的整体性能却大幅下降(甚至无法支持每分钟5000个请求)我能够使用较小的RDS。)

我在许多方面处于不熟悉的领域,并且不确定如何在每分钟超过5000个请求时最好地确定哪些移动部件是瓶颈API性能。如上所述,我已根据对Postgresql配置文档和node-postgres文档的审核尝试了各种调整,但无济于事。

如果有人就如何诊断或优化提出建议,我会非常感激。

更新

在扩展到m4.10xlarge之后,我执行了一系列的负载测试,改变了每个池中请求/分钟数和最大连接数。以下是监控指标的一些屏幕截图:

monitoring metrics

db connections

3 个答案:

答案 0 :(得分:5)

为了支持超过5k的请求,同时保持相同的响应速度,您需要更好的硬件......

简单的数学表明: 5000 requests*190ms avg = 950k ms divided into 16 cores ~ 60k ms per core  这基本上意味着你的系统负载很高 (我猜你有一些备用的CPU因为网络上有时间丢失了)

现在,您问题中真正有趣的部分来自扩展尝试:m4.10xlarge(160 GB内存,40个vCPU)。
CPU利用率下降表明扩展会释放数据库时间资源 - 因此您需要推送更多请求! 2意见建议:

  • 尝试将连接池增加到max: 70并查看网络流量(取决于您可能占用网络的数据量)
  • 另外,您是否向应用程序端请求数据库同步?确保您的应用实际上可以推送更多请求。

答案 1 :(得分:1)

根据我的经验,API服务最好的办法是根据呼叫的优先级为每个API调用使用单独的Pool

var highPriority = new Pool({...max: 20}); // for high-priority API calls
var lowPriority = new Pool({...max: 5}); // for low-priority API calls

然后,您只需为每个API调用使用正确的池,以获得最佳的服务可用性。

答案 2 :(得分:0)

由于您对读取性能感兴趣,可以在两个(或更多)PostgreSQL实例之间设置复制,然后使用pgpool II在实例之间进行负载平衡。

横向缩放意味着如果您下周需要进行10,000次并发读取,则无法在AWS上开始达到最大实例大小。

您也开始在您的架构中获得一些HA。

-

很多时候人们会使用pgbouncer作为连接池,即使他们已经在应用程序代码中内置了一个。 pgbouncer工作得很好,通常更容易配置和管理pgpool,但它没有做负载平衡。我不确定在这种情况下它是否对你有很大的帮助。