背景:
在生产过程中,我们有一个鲜为人知的错误,它偶尔会发生(每周更频繁(,有时可能会导致整个应用程序瘫痪,有时甚至只是我们所有的后台流程。不幸的是,我不确定是什么原因导致了这个问题,下面是我的工作理论——你能验证一下它的逻辑吗?
停机前的错误(在几秒钟内发生几百次(是PostgreSQL错误FATAL: sorry, too many clients already
。
工作原理:
API的各个部分可以请求与数据库的连接。例如,在我们的RubyonRails应用程序中,我们有12个puma工作线程和16个线程(12*16=192个可能的数据库连接(。此外,我们有10个后台工作者,每个人都可以连接一个数据库。如果我们还考虑一个具有1个数据库连接的SSH会话,那么我们必须预期的最大数据库连接量是192 + 10 + 1 = 203
PostgreSQL连接,在postgresql.conf
配置文件中使用max_connections
设置。
然而,我们的max_connections
仍然设置为PostgreSQL默认值100
。我的理解是,这是有问题的:当应用程序认为可能有更多的数据库连接时(查看puma和后台工作人员的应用程序端设置(,它允许建立新的数据库连接。但是当这些与PostgreSQL的连接启动时,PostgreSQL会查看自己设置的最多100个连接,并断开连接。
相反,当";可请求的";连接(在这种情况下为203(将低于或等于PostgreSQLmax_connections
,它将利用pool timeout
排队到请求的数据库连接,直到数据库套接字可用。
这是可取的,因为在池超时内可能会解决太多的连接。因此,我们的问题的解决方案是使;可请求的";数据库连接=<可能的数据库连接。如果这还不够,我应该增加100个可能的连接。
这有意义吗
任何想法或批评都将不胜感激
您的应用程序线程不需要将1-1映射到数据库连接。您可以将连接池用于数据库连接。看见https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html
在上也有很多关于这个主题的好信息https://devcenter.heroku.com/articles/concurrency-and-database-connections