Rails Puma 频繁产生 CLOSE_WAIT 导致无响应?

xsown · 2019年05月16日 · 最后由 kalel 回复于 2019年05月22日 · 583 次阅读

nginx + puma,rails 5,纯api模式提供json接口

不定期出现所有接口都无响应的症状,去服务器lsof的结果:非常多的CLOSE_WAIT,如下图:

此时只能kill puma进程然后重开。

nginx配置:

puma.rb:

database.yml:

请问大佬们,可能是什么原因?有什么彻底的解决方法么?(手动抠鼻)

共收到 15 条回复

看上去都是数据库?

加大点 pool 比如 30 - 50 试试 ?

把数据库的pool 设置为50及以上试试。 用 ab 先压一下,确定问题

@jicheng1014 @awking pool 的大小应该为 cpu核心数*2 + 磁盘数

kikyous 回复

怎么得出来的

A connection pool synchronizes thread access to a limited number of database connections. The basic idea is that each thread checks out a database connection from the pool, uses that connection, and checks the connection back in. ConnectionPool is completely thread-safe, and will ensure that a connection cannot be used by two threads at the same time, as long as ConnectionPool's contract is correctly followed. It will also handle cases in which there are more threads than connections: if all connections have been checked out, and a thread tries to checkout a connection anyway, then ConnectionPool will wait until some other thread has checked in a connection. pool的值应该与puma最大thread数一致,大于thread数其实是无效的。

Terry.Shi 回复

这个线程池个数设置方式 应该比较靠谱.

特例是, 在puma 的一个 thread 里并行用到了一个以上的连接. 但是似乎我也没想到这种情况的场景.

而且算法是在 puma max threads的情况下的, 一般压力不会那么大

kikyous 回复

简化一下情况

假设运行后端的服务器只有1核的CPU

之后开一个 PUMA , puma 跑20 个线程,

现在有大量数据库事务的任务,每个事务执行需要1s,

再假设除了执行数据库, 其他操作小于1ms 的响应

如果pool的大小是2, 那么是不是此时就只能并发两个请求?

是否能等效理解为 在执行事务的时候, 此时服务器的cpu 是空闲状态, 但是却因为数据库连接池的问题不能进行服务?

如果此时连接池开到20, 将puma 的线程池满

似乎就可以进入20个并发了

或者我的理解有问题, 有一些概念上的错误?

jicheng1014 回复

我的理解是: 线程数也是和cpu数量相关的,1核的cpu,你线程设置成20,反而使cpu花费大量时间做上下文切换,导致性能降低。 所以我认为puma线程数,数据库连接池都应和 cpu 数量挂钩的

直接用pg bouncer吧,不要让puma管理连接池了

kikyous 回复

cpu是跟puma进程数挂钩的吧。IO wait puma多线程就管用了... DB pool是要跟puma线程数挂钩的吧,如果20个线程全在跑,pool数为2,那显然是不够用...

kikyous 回复

在我举的例子当中, 当进行数据库事务的时候 本机的 CPU 是闲置的状态, 这个时候切换上下文是会提高cpu 效率的, 而这种情况的变种我觉得还经常会发生(瓶颈在数据库). 所以我会对您那个公式有点不同意见

13楼 已删除

将pool 和PUMA的线程数配置 增大。你配 5 对现在的系统服务应该小了

这是数据库池问题,与puma没有直接关系。建议你看看postgresql 的log。你的连接被数据库关闭了。

你可以查看一下 postgresql 的配置文件, 检查下,下面三项配置,可以参考这里

tcp_keepalives_idle
tcp_keepalives_interval
tcp_keepalives_count
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册