首页 > 解决方案 > 乘客使用的 PostgreSQL 连接比预期的要多

问题描述

生产中长期发生的难题,我们不知道它来自哪里。有时可以在 localhost 上重现它,Heroku Enterprise 支持对此一无所知。

在我们的生产数据库中,我们目前有以下设置:

aSELECT * FROM pg_stat_activity GROUP BY client_addr并计算每个实例的连接数表明在我们的高峰期为一个乘客进程打开了超过 1 个 PSQL 连接。

假设:

这是看起来的屏幕截图SELECT * FROM pg_stat_activity;

在此处输入图像描述 在屏幕截图中,我们可以看到有45 个 psql 连接来自运行乘客的同一台测功机。如果我们按照之前的逻辑,每个Passenger进程的连接不应该超过1个,所以25个。

日志看起来并不异常,没有提到测功机崩溃/进程崩溃。

这是我们对同一个测功机的乘客状态的屏幕截图(不同的时间,只是为了证明为一个测功机创建的进程不超过 25 个): 在此处输入图像描述

最后是我们从 Heroku 支持中得到的回应之一(Amazing support btw)

我还看到过有关乘客使用比预期更多的连接的先前报告,但不幸的是,大多数由于难以复制而被关闭。

在乘客文档中,解释了乘客自己处理 ActiveRecord 连接。

任何线索表示赞赏。谢谢!

各种资料:

如果您需要更多信息,请在评论中告诉我,我会很乐意更新这篇文章。

最后一件事:我们使用 ActionCable。我在某处读到乘客正在奇怪地处理套接字连接(打开一个有点隐藏的过程以保持连接处于活动状态)。这是我们的线索之一,但到目前为止,在 localhost 上复制它还没有运气。如果有人可以确认乘客如何处理 ActionCable 连接,将不胜感激。

更新 1(2018 年 1 月 10 日):

实验:

标签: ruby-on-railspostgresqlherokupassengeractioncable

解决方案


我们终于设法解决了关于乘客的问题。实际上,我们已经有这个问题很长时间了。

修复

如果您使用 ActionCable,并且您的默认电缆路线是/cable,则将 Procfile 更改为:

web: bundle exec passenger start -p $PORT --max-pool-size $PASSENGER_MAX_POOL_SIZE

web: bundle exec passenger start -p $PORT --max-pool-size $PASSENGER_MAX_POOL_SIZE --unlimited-concurrency-path /cable

解释

在更改之前,每个套接字连接 (ActionCable) 将在Passenger 中占用一个进程。但是一个 Socket 实际上是不应该占用整个过程的东西。一个进程可以处理许多打开的套接字连接。(对于一些大牌来说,很多同时超过一万)。幸运的是,我们的套接字连接要少得多,但仍然如此。

改完之后,我们基本上告诉Passenger不要用一整个进程来处理一个socket连接,而是专门用一个进程来处理所有的socket连接。

文档

修复 3 周后的一些指标

  • 乘客上的分叉进程数量显着减少(从 75 个进程到约 15 个进程)
  • Web dynos 上的全局内存使用量急剧下降(与前一点关于分叉的乘客进程有关)
  • PSQL 连接的全球数量急剧下降,并且已经稳定了两天(即使在部署之后)。(从 150 到 ~30 个连接)
  • 每个测功机的 PSQL 连接数显着减少(从每个测功机约 50 个到每个测功机不到 10 个)
  • Redis 连接数减少,并且已经稳定了两天(即使在部署之后)
  • PostgreSQL 上的平均内存使用量急剧下降,并且已经稳定了两天。
  • 整体吞吐量比平时高一点(吞吐量是每分钟处理的请求数)

推荐阅读