Rails 空闲时停止响应
Rails stops responding if Idle
我遇到这个问题有一段时间了,也搜索了很多,但似乎没有什么能解决我的问题。
我有一个应用程序 运行ning in Ruby on Rails with NGINX and UNICORN everything with Docker.
如果我 运行 应用程序(docker-编写)网站 运行 完美几分钟。如果网站闲置大约 5 到 10 分钟,然后我发送另一个请求,rails 应用程序停止响应,让 Unicorn 超时。
奇怪的是,我开发的每个应用程序都有相同的问题,这些应用程序唯一的共同点是 Gemfile。
到目前为止我发现的是,当发送请求时,NGINX 收到这个请求,将它传递给 Unicorn,Unicorn 接收它并传递给 ruby... 它没有回答,然后 Unicorn给我 502 错误请求。
我真的迷失在这一点上。
这是我的 NGINX 配置文件:
upstream applicationName {
# Path to Puma SOCK file, as defined previously
server unix:/tmp/applicationName.sock fail_timeout=0;
}
server {
listen 80;
server_name dev.applicationName.com.br;
location / {
autoindex on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
# time out settings
proxy_connect_timeout 159s;
proxy_send_timeout 600;
proxy_read_timeout 600;
proxy_buffer_size 64k;
proxy_buffers 16 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_pass_header Set-Cookie;
proxy_redirect off;
proxy_hide_header Vary;
proxy_set_header Accept-Encoding '';
proxy_ignore_headers Cache-Control Expires;
proxy_set_header Referer $http_referer;
proxy_set_header Host $host;
proxy_set_header Cookie $http_cookie;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://applicationName;
}
}
这是我的独角兽配置
@dir = File.expand_path(File.dirname(__FILE__)) + "/.."
worker_processes 2
working_directory @dir
timeout 10
listen File.join('/tmp/applicationName.sock')
preload_app true# if ENV['RAILS_ENV'] != 'development'
GC.respond_to?(:copy_on_write_friendly=) and
GC.copy_on_write_friendly = true
check_client_connection false
before_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
end
after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
end
这是 Gemfile(没有问题)
source 'https://rubygems.org'
gem 'rails', '4.2.4'
gem 'unicorn-rails', '~> 2.2'
gem 'pg'
gem 'mysql2', '~> 0.3.18'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.1.0'
gem 'duktape'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'bootstrap-sass'
gem 'devise'
gem 'simple_form'
gem 'minitest'
gem "paperclip", "~> 4.3"
gem 'aws-sdk', '< 2.0'
gem 'mail_form', '~> 1.5.0.rc'
gem 'sendgrid-ruby'
gem 'zopim_rails'
gem 'meta-tags'
gem 'ckeditor'
gem 'slick_rails'
group :development do
gem 'better_errors'
gem 'binding_of_caller', :platforms=>[:mri_20]
gem 'quiet_assets'
gem 'rails_layout'
gem 'spring-commands-rspec'
gem 'web-console', '~> 2.0'
gem 'spring'
end
group :production do
gem 'therubyracer'
end
group :development, :test do
gem 'factory_girl_rails'
gem 'faker'
gem 'pry-rails'
gem 'pry-rescue'
gem 'rspec-rails'
gem 'rubocop'
gem 'byebug'
end
group :test do
gem 'capybara'
gem 'database_cleaner'
gem 'launchy'
gem 'selenium-webdriver'
end
当错误发生时,服务器上的日志显示如下:
nginx_1 | 172.17.0.1 - - [05/Feb/2016:12:52:41 +0000] "GET /products HTTP/1.1" 502 574 "http://dev.nutrimais.com.br/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.82 Safari/537.36"
web_1 | E, [2016-02-05T12:52:41.551728 #1] ERROR -- : reaped #<Process::Status: pid 9 SIGKILL (signal 9)> worker=0
在开发日志中:
Started GET "/products" for 127.0.0.1 at 2016-02-05 12:52:18 +0000
Cannot render console from 127.0.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
我听说过 unicorn 的此类问题,如果一个站点在大约(平均)30 分钟内未被访问,则下一个查询将超时,并且所有打开的工作人员都会超时。我不确定为什么会这样。
希望以下 link 对您有所帮助
事实上,这是我的 Linux 服务器的防火墙和位于另一台服务器上的数据库的问题。我所做的是将数据库服务器与我的 rails 应用程序放在同一台机器上。另一种修复方法是更改服务器计算机的防火墙规则。我还没有这样做,也不知道该怎么做。看起来这个问题只发生在 MySQL.
您将 MySQL 移动到同一台服务器的解决方法也解决了我的问题,但这不适合我的生产环境,因此我更深入地研究了该设置的不同之处。
原来这与应用程序堆栈或配置无关,而是 NAT 超时导致我的会话终止。
我的服务器在 Azure 上,数据库在 AWS 上。 Azure 在出站连接上有 4 分钟不可配置的 NAT 超时。这意味着如果数据库连接空闲超过 4 分钟,Azure 将静静地终止端口映射,并且 Rails 应用程序试图发送到该端口的任何流量静静地进入黑洞。
根据 this blob 在 Rails 服务器上 OS 级别进行了修复:将 TCP 保活间隔降低到 NAT 超时的一半,并将保活间隔和重新传输调整为新保持活动间隔的适当值。
对于Linux,您应该按如下方式更改这些内核变量:
sudo sysctl net.ipv4.tcp_keepalive_time = 120
sudo sysctl net.ipv4.tcp_keepalive_intvl = 30
sudo sysctl net.ipv4.tcp_keepalive_probes = 8
对于 Windows,您应该更改以下注册表值。
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
中的所有 DWORD
:
KeepAliveInterval = 30
KeepAliveTime = 120
TcpMaxDataRetransmissions = 8
我遇到这个问题有一段时间了,也搜索了很多,但似乎没有什么能解决我的问题。
我有一个应用程序 运行ning in Ruby on Rails with NGINX and UNICORN everything with Docker.
如果我 运行 应用程序(docker-编写)网站 运行 完美几分钟。如果网站闲置大约 5 到 10 分钟,然后我发送另一个请求,rails 应用程序停止响应,让 Unicorn 超时。
奇怪的是,我开发的每个应用程序都有相同的问题,这些应用程序唯一的共同点是 Gemfile。
到目前为止我发现的是,当发送请求时,NGINX 收到这个请求,将它传递给 Unicorn,Unicorn 接收它并传递给 ruby... 它没有回答,然后 Unicorn给我 502 错误请求。
我真的迷失在这一点上。
这是我的 NGINX 配置文件:
upstream applicationName {
# Path to Puma SOCK file, as defined previously
server unix:/tmp/applicationName.sock fail_timeout=0;
}
server {
listen 80;
server_name dev.applicationName.com.br;
location / {
autoindex on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
# time out settings
proxy_connect_timeout 159s;
proxy_send_timeout 600;
proxy_read_timeout 600;
proxy_buffer_size 64k;
proxy_buffers 16 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_pass_header Set-Cookie;
proxy_redirect off;
proxy_hide_header Vary;
proxy_set_header Accept-Encoding '';
proxy_ignore_headers Cache-Control Expires;
proxy_set_header Referer $http_referer;
proxy_set_header Host $host;
proxy_set_header Cookie $http_cookie;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://applicationName;
}
}
这是我的独角兽配置
@dir = File.expand_path(File.dirname(__FILE__)) + "/.."
worker_processes 2
working_directory @dir
timeout 10
listen File.join('/tmp/applicationName.sock')
preload_app true# if ENV['RAILS_ENV'] != 'development'
GC.respond_to?(:copy_on_write_friendly=) and
GC.copy_on_write_friendly = true
check_client_connection false
before_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
end
after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
end
这是 Gemfile(没有问题)
source 'https://rubygems.org'
gem 'rails', '4.2.4'
gem 'unicorn-rails', '~> 2.2'
gem 'pg'
gem 'mysql2', '~> 0.3.18'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.1.0'
gem 'duktape'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'bootstrap-sass'
gem 'devise'
gem 'simple_form'
gem 'minitest'
gem "paperclip", "~> 4.3"
gem 'aws-sdk', '< 2.0'
gem 'mail_form', '~> 1.5.0.rc'
gem 'sendgrid-ruby'
gem 'zopim_rails'
gem 'meta-tags'
gem 'ckeditor'
gem 'slick_rails'
group :development do
gem 'better_errors'
gem 'binding_of_caller', :platforms=>[:mri_20]
gem 'quiet_assets'
gem 'rails_layout'
gem 'spring-commands-rspec'
gem 'web-console', '~> 2.0'
gem 'spring'
end
group :production do
gem 'therubyracer'
end
group :development, :test do
gem 'factory_girl_rails'
gem 'faker'
gem 'pry-rails'
gem 'pry-rescue'
gem 'rspec-rails'
gem 'rubocop'
gem 'byebug'
end
group :test do
gem 'capybara'
gem 'database_cleaner'
gem 'launchy'
gem 'selenium-webdriver'
end
当错误发生时,服务器上的日志显示如下:
nginx_1 | 172.17.0.1 - - [05/Feb/2016:12:52:41 +0000] "GET /products HTTP/1.1" 502 574 "http://dev.nutrimais.com.br/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.82 Safari/537.36"
web_1 | E, [2016-02-05T12:52:41.551728 #1] ERROR -- : reaped #<Process::Status: pid 9 SIGKILL (signal 9)> worker=0
在开发日志中:
Started GET "/products" for 127.0.0.1 at 2016-02-05 12:52:18 +0000
Cannot render console from 127.0.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
我听说过 unicorn 的此类问题,如果一个站点在大约(平均)30 分钟内未被访问,则下一个查询将超时,并且所有打开的工作人员都会超时。我不确定为什么会这样。 希望以下 link 对您有所帮助
事实上,这是我的 Linux 服务器的防火墙和位于另一台服务器上的数据库的问题。我所做的是将数据库服务器与我的 rails 应用程序放在同一台机器上。另一种修复方法是更改服务器计算机的防火墙规则。我还没有这样做,也不知道该怎么做。看起来这个问题只发生在 MySQL.
您将 MySQL 移动到同一台服务器的解决方法也解决了我的问题,但这不适合我的生产环境,因此我更深入地研究了该设置的不同之处。
原来这与应用程序堆栈或配置无关,而是 NAT 超时导致我的会话终止。
我的服务器在 Azure 上,数据库在 AWS 上。 Azure 在出站连接上有 4 分钟不可配置的 NAT 超时。这意味着如果数据库连接空闲超过 4 分钟,Azure 将静静地终止端口映射,并且 Rails 应用程序试图发送到该端口的任何流量静静地进入黑洞。
根据 this blob 在 Rails 服务器上 OS 级别进行了修复:将 TCP 保活间隔降低到 NAT 超时的一半,并将保活间隔和重新传输调整为新保持活动间隔的适当值。
对于Linux,您应该按如下方式更改这些内核变量:
sudo sysctl net.ipv4.tcp_keepalive_time = 120
sudo sysctl net.ipv4.tcp_keepalive_intvl = 30
sudo sysctl net.ipv4.tcp_keepalive_probes = 8
对于 Windows,您应该更改以下注册表值。
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
中的所有 DWORD
:
KeepAliveInterval = 30
KeepAliveTime = 120
TcpMaxDataRetransmissions = 8