x 时间后套接字无响应 (puma - ruby)

Unresponsive socket after x time (puma - ruby)

我的 Puma 设置在随机时间后遇到无响应的套接字。到目前为止,我不知道是什么导致了这个问题。我希望这里有人可以帮助我们提供一些答案或为我指明正确的方向。我有以下设置:

我使用的是官方docker ruby-2.2.3-slim 镜像和最新的puma 版本2.15.3,我还安装了Nginx 作为反向代理。但我已经确定 Nginx 不是这里的问题,因为我已经尝试使用此 script 验证套接字是否正常工作。而且套接字不工作,我在那里也有超时,所以我可以忽略 Nginx。

这是一个测试环境,因此服务器没有遇到任何极端负载,我还检查了内存消耗,它仍有几 GB 的可用空间 space,所以这也不是问题。 促使我查看 puma 套接字的是我在 Nginx 错误日志记录中收到的错误消息:

upstream timed out (110: Connection timed out) while reading response header from upstream

此外,我在 puma 的日志中找不到任何指示出了什么问题的信息,这是我的 puma 设置:

threads 0, 16

app_dir = ENV.fetch('APP_HOME')
environment ENV['RAILS_ENV']

daemonize

bind "unix://#{app_dir}/sockets/puma.sock"
stdout_redirect "#{app_dir}/log/puma.stdout.log", "#{app_dir}/log/puma.stderr.log", true

pidfile "#{app_dir}/pids/puma.pid"
state_path "#{app_dir}/pids/puma.state"
activate_control_app

on_worker_boot do
  require 'active_record'
  ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
  ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[ENV['RAILS_ENV']])
end

这是我的 puma 状态文件中的输出:

---
pid: 43
config: !ruby/object:Puma::Configuration
  cli_options:
  conf:
  options:
    :min_threads: 0
    :max_threads: 16
    :quiet: false
    :debug: false
    :binds:
    - unix:///APP/sockets/puma.sock
    :workers: 1
    :daemon: true
    :mode: :http
    :before_fork: []
    :worker_timeout: 60
    :worker_boot_timeout: 60
    :worker_shutdown_timeout: 30
    :environment: staging
    :redirect_stdout: "/APP/log/puma.stdout.log"
    :redirect_stderr: "/APP/log/puma.stderr.log"
    :redirect_append: true
    :pidfile: "/APP/pids/puma.pid"
    :state: "/APP/pids/puma.state"
    :control_url: unix:///tmp/puma-status-1449260516541-37
    :config_file: config/puma.rb
    :control_url_temp: "/tmp/puma-status-1449260516541-37"
    :control_auth_token: cda8879717be7a645ea323d931b88d4b
    :tag: APP

该应用程序本身是一个 Rails 最新版本 4.2.5 上的应用程序,它部署在 GCE(Google 容器引擎)上。

如果有人能给我一些关于如何进一步调试它的指示,将不胜感激。因为现在我在任何地方都看不到任何可以帮助我的输出。

编辑

我用到 Puma 的 tcp 连接替换了 unix 套接字,结果相同,x 时间后仍然挂起

我会从:

开始
  • 每个 puma 实例成功处理了多少个请求?
  • 确保使用执行它的线程的线程 ID 记录每个请求的开始和结束,您看到了什么?

我对您的应用程序了解不多,我想说线程很可能在执行一些 long/blocking 没有超时的调用或在某些计算上自旋,直到整个线程池耗尽。

我们拭目以待。

我终于找到了为什么我的应用程序表现如此。 在尝试使用 tcp 连接并切换到 Unicorn 后,我开始研究其他可能的来源。

那时我认为我与 Google Cloud SQL 的连接可能是问题所在。在我阅读 Cloud SQL 的常见问题解答后,他们提到您必须调整您的 Compute 实例以确保它们保持打开您的数据库连接。所以我执行了他们推荐的后续步骤并为我解决了问题,我添加了它们以防万一:

# Display the current tcp_keepalive_time value.
$ cat /proc/sys/net/ipv4/tcp_keepalive_time

# Set tcp_keepalive_time to 60 seconds and make it permanent across reboots.
$ echo 'net.ipv4.tcp_keepalive_time = 60' | sudo tee -a /etc/sysctl.conf

# Apply the change.
$ sudo /sbin/sysctl --load=/etc/sysctl.conf

# Display the tcp_keepalive_time value to verify the change was applied.
$ cat /proc/sys/net/ipv4/tcp_keepalive_time