我正在运行7个sidekiq进程(货币设置为40)以及一个乘客网络服务器,连接到postgres数据库。 Rails池设置设置为100,postgres max_connections设置也是默认值100。
我刚刚添加了一个新的工作类,其中每个工作都会发出多个postgres请求,我开始在许多sidekiq工作中收到此错误,有时在我的网络服务器上:PG::ConnectionBad: FATAL: remaining connection slots are reserved for non-replication superuser connections
我尝试将postgres max_connections增加到200,但错误仍然存在。然后我尝试将activerecord池设置减少到25(每个进程25个连接= 200个总连接),这意味着我可能会开始得到数据库连接超时错误但至少它会停止"没有剩余的连接时隙"错误。
但我仍然收到remaining connection slots are reserved
错误。
处理这个问题的更聪明的方法可能是加载我不断重用redis的重要postgres数据,然后从redis访问它 - 这可以通过sidekiq更好地和快速地播放。但即使我这样做,我也想通过postgres连接了解这里发生了什么:
(见Releasing ActiveRecord connection before the end of a Sidekiq job)
(参见https://github.com/mperham/sidekiq/issues/594。我认为我使用ActiveRecord非常简单,对于rails应用程序没有太多模糊或异常的逻辑......)
答案 0 :(得分:6)
我的情况可能过于具体,无法帮助许多其他人遇到此错误,但我会分享我发现的内容,以防它指向正确的方向。
我是否可能泄漏连接,是否应该在sidekiq工作中管理?
不,不太可能。即使作业失败,Sidekiq的默认中间件也包括a hook to close connections。我花了很长时间才明白这意味着什么,所以如果你不确定这意味着什么,那么,如果你正常使用它,那么: Sidekiq不会泄漏连接。
我是否应该查看更多模糊的内容,例如锁定/争用问题或PG驱动程序的线程问题?
除非你使用的是非常模糊的设置,否则它可能更简单。
或者我可能只是不了解ActiveRecord池设置和postgres max_connection设置如何协同工作......
如果我错了,任何人都可以随意纠正我,但这里是我正在进行的游泳池设置,max_connections和sidekiq流程的指导原则:
最小数据库池大小= sidekiq并发设置
最大数据库池大小* = postgres max_connections / total sidekiq进程(+为Web进程留下一些连接)
*请注意,当新线程需要一个时,活动记录只会创建一个新连接,所以如果你的95%的线程不同时使用postgres,你应该能够远远少于max_connections。如果每个线程都试图同时检出连接。
解决了我的问题:
在我的Ubuntu机器上,我将vm.overcommit_memory
设置更改为1 as recommended by redis,这样就可以在不破坏机器的情况下将其写入磁盘进程。
这是正确的方法,但是如果内存使用率太高,那么就会让OgI(内存不足)很容易被杀死。事实证明,如果从OOM Killer收到一个终止信号,postgres将停止允许新连接。
一旦我重新启动postgres,sidekiq就可以再次连接。长期解决方案只是处理内存泄漏并确保内存使用不会太高。此外,还可以配置OOM杀手,以便在杀死postgres之前优先杀死我的sidekiqs。