【问题标题】:Debugging unicorn postgres connection leak调试独角兽 postgres 连接泄漏
【发布时间】:2016-04-07 18:13:25
【问题描述】:

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

PG max_connections = 100 独角兽工人 = 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)

奇怪的是,我看到多个连接归因于单个独角兽工作进程。

我读对了吗?我的假设是,这是导致重大负载时 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

database.yml -

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

【问题讨论】:

    标签: ruby-on-rails postgresql database-connection


    【解决方案1】:

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

    池最大可以达到pooldatabase.yml中的配置选项)大。因此,如果您将pool 选项设置为 40,则每个 进程(独角兽工作者)在使用 40 个(或更多)线程时最多可以打开 40 个连接,所以在你的情况下,独角兽可能会吃掉多达 40 * 8 = 200 个连接

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

    【讨论】:

      【解决方案2】:

      不久前有一个类似的问题,未使用的连接处于打开状态。对我来说PgBouncer 修复了它

      【讨论】:

      • 谢谢。我也决定使用 PgBouncer。但我想在安装此工具解决问题之前找出为什么会发生这种情况:)
      猜你喜欢
      • 2014-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-28
      • 2014-01-15
      • 2012-01-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多