ruby-on-rails - 调试 unicorn postgres 连接泄漏

标签 ruby-on-rails postgresql database-connection

我们的新应用昨天流量很大,开始崩溃。错误是达到 PG 最大连接数。考虑到我们的配置,这非常奇怪 -

PG max_connections = 100 unicorn worker = 8 Sidekiq 进程 = 1 Sidekiq 并发 = 25

所以从技术上讲应该只有 34 个事件连接,对吗?我认为我们的应用程序中没有任何多线程。

在我重新启动数据库服务器和应用程序后,这个问题就解决了。今天,我开始看到这些连接弹出。

检查pg_stats_activity:

prod_db=# select datid, datname, pid, usesysid, usename, application_name, state from pg_stat_activity;                                                                             
 datid |        datname        |  pid  | usesysid | usename  |                        application_name                         | state  
-------+-----------------------+-------+----------+----------+-----------------------------------------------------------------+--------
 16384 | prod_db | 30104 |       10 | postgres | unicorn worker[1] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db | 30094 |       10 | postgres | unicorn worker[0] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db | 30110 |       10 | postgres | unicorn worker[2] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db | 30116 |       10 | postgres | unicorn worker[3] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db | 30123 |       10 | postgres | unicorn worker[4] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db | 30129 |       10 | postgres | unicorn worker[5] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db | 30135 |       10 | postgres | unicorn worker[6] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db | 30157 |       10 | postgres | unicorn worker[7] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db | 32161 |       10 | postgres | unicorn worker[5] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db | 32183 |       10 | postgres | unicorn worker[7] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db | 32273 |       10 | postgres | unicorn worker[5] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db | 32296 |       10 | postgres | unicorn worker[2] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db |   374 |       10 | postgres | unicorn worker[1] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db |   491 |       10 | postgres | sidekiq 3.4.2 app_production [0 of 25 busy]                     | idle
 16384 | prod_db |   498 |       10 | postgres | unicorn worker[7] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db |   581 |       10 | postgres | unicorn worker[3] -c /u/apps/e...ig/unicorn.rb -E deployment -D | idle
 16384 | prod_db |  1337 |       10 | postgres | psql                                                            | active
(17 rows)

我看到多个连接归因于单个 unicorn 工作进程,这很奇怪。

我读的对吗?我的假设是,这是导致 postgres 连接在有重大负载时耗尽这一致命事件的基石。

如果这是真的,如何调试呢?任何指针?谢谢! :)

如果需要,很乐意分享更多详细信息。

postgresql.conf

data_directory = '/var/lib/postgresql/9.4/main'
datestyle = 'iso, mdy'
default_text_search_config = 'pg_catalog.english'
external_pid_file = '/var/run/postgresql/9.4-main.pid'
hba_file = '/etc/postgresql/9.4/main/pg_hba.conf'
ident_file = '/etc/postgresql/9.4/main/pg_ident.conf'
listen_addresses = 'localhost'
log_line_prefix = '%t '
max_connections = 100
port = 5432
shared_buffers = '24MB'
ssl = on
ssl_cert_file = '/etc/ssl/certs/ssl-cert-snakeoil.pem'
ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key'
unix_socket_directories = '/var/run/postgresql'

unicorn.rb - https://gist.github.com/steverob/b83e41bb49d78f9aa32f79136df5af5f

数据库.yml -

production:
  adapter: postgresql
  host: localhost
  username: postgres
  password: app_name
  pool: 40
  timeout: 5000
  database: app_production
  encoding: utf8

最佳答案

一般来说,应用程序中的任何线程,当它在数据库中执行查询时(即当它以任何方式使用 ActiveRecord::Base.connection 时),它都会获得到DB,与其他线程分开ConnectionPool class负责将数据库连接分配给 Rails 中的线程。请阅读类(class)文档以获取更多信息。

池最大可达pool(database.yml 中的配置选项)。因此,如果将 pool 选项设置为 40,则每个 process(unicorn worker)如果使用 40(或更多)threads<,则最多可以打开 40 个连接/em>,所以在您的情况下,仅 unicorn 就可能吃掉多达 40 * 8 = 200 个连接

因此,总的来说,我认为您的应用程序中一定有一些线程(可能在某个 gem 中)。如果这与您的 other question 中的应用程序相同,那么我猜这肯定与多个生成线程有关。

关于ruby-on-rails - 调试 unicorn postgres 连接泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36484097/

相关文章:

通过 javascript_include_tag 可用的 javascript 函数,但不是 Assets 管道和 application.js

sql - 按顺序找不到聚合列

php - 无法连接到 MySQL - 断电后丢失东西?

html - 如何将隐藏表格放入表格中?

ruby-on-rails - Rails thin 停止使用 pid

ruby-on-rails - 将数据工具提示添加到简单的表单语法?

postgresql - 从 PostgreSQL 中删除未命名的约束

postgresql - 从 PostgreSQL 数据库中检索评论

c++ - 无法使用 MySQL Connector/C++ : exception thrown 从 C++ 程序连接到 MySQL 数据库

针对 PostgreSQL 8.4.6 的 java.sql.Connection 测试