为何我的 Rails 应用程序挂起了?

为何我的 Rails 应用程序挂起了?

我有一个中等复杂度的 Rails 应用程序在 Apache/Passenger 下运行,它在空闲一段时间后变得无响应。它需要几分钟才能响应,但可以通过重新启动 Web 服务器暂时恢复。

服务器负载可以忽略不计,而且由于它是内部应用程序,所以很少有超过几个并发用户。

我也尝试过 nginx,所以问题不是由 Apache 引起的。

Apache 或 Rails 日志中没有任何有用的信息。根据 Passenger 文档,我发送了 SIGABRT 并有一个堆栈跟踪(如下)。它的数据库负载不重,我尝试禁用可能导致锁定的任何后台处理。

信号异常(SIGABRT):
  乘客(3.0.17)lib / phusion_passenger / abstract_request_handler.rb:443:在`install_useful_signal_handlers中的阻止'
  activerecord (3.2.8) lib/active_record/connection_adapters/mysql2_adapter.rb:73:in`调用'
  activerecord (3.2.8) lib/active_record/connection_adapters/mysql2_adapter.rb:73:in `ping'
  activerecord (3.2.8) lib/active_record/connection_adapters/mysql2_adapter.rb:73:in`活动?'
  activerecord (3.2.8) lib/active_record/connection_adapters/abstract_adapter.rb:219:在`验证!'
  activerecord (3.2.8) lib/active_record/connection_adapters/abstract/connection_pool.rb:327:in`在 checkout_and_verify 中阻止'
  activesupport (3.2.8) lib/active_support/callbacks.rb:403:在`_run__352340970312725798__checkout__1600727162984137669__callbacks'中
  activesupport (3.2.8) lib/active_support/callbacks.rb:405:在`__run_callback'中
  activesupport (3.2.8) lib/active_support/callbacks.rb:385:in `_run_checkout_callbacks'
  activesupport (3.2.8) lib/active_support/callbacks.rb:81:在`run_callbacks'中
  activerecord (3.2.8) lib/active_record/connection_adapters/abstract/connection_pool.rb:326:in`checkout_and_verify'
  activerecord (3.2.8) lib/active_record/connection_adapters/abstract/connection_pool.rb:247:in `块(2 级)在结帐中'
  activerecord (3.2.8) lib/active_record/connection_adapters/abstract/connection_pool.rb:236:in `循环'
  activerecord (3.2.8) lib/active_record/connection_adapters/abstract/connection_pool.rb:236:in`阻止签出'
  /home/uuuuu/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/monitor.rb:211:in`mon_synchronize'
  activerecord (3.2.8) lib/active_record/connection_adapters/abstract/connection_pool.rb:233:in `checkout'
  activerecord (3.2.8) lib/active_record/connection_adapters/abstract/connection_pool.rb:96:in`连接阻塞'
  /home/uuuuu/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/monitor.rb:211:in`mon_synchronize'
  activerecord (3.2.8) lib/active_record/connection_adapters/abstract/connection_pool.rb:95:in `连接'
  activerecord (3.2.8) lib/active_record/connection_adapters/abstract/connection_pool.rb:404:in`retrieve_connection'
  activerecord (3.2.8) lib/active_record/connection_adapters/abstract/connection_specification.rb:170:in`retrieve_connection'
  activerecord (3.2.8) lib/active_record/connection_adapters/abstract/connection_specification.rb:144:in `连接'
  activerecord (3.2.8) lib/active_record/query_cache.rb:61:in `调用'
  activerecord (3.2.8) lib/active_record/connection_adapters/abstract/connection_pool.rb:473:in`调用'
  actionpack (3.2.8) lib/action_dispatch/middleware/callbacks.rb:28:in`调用中的阻止'
  activesupport (3.2.8) lib/active_support/callbacks.rb:405:在`_run__1086758471249540907__call__1600727162984137669__callbacks'中
  activesupport (3.2.8) lib/active_support/callbacks.rb:405:在`__run_callback'中
  activesupport (3.2.8) lib/active_support/callbacks.rb:385:in `_run_call_callbacks'
  activesupport (3.2.8) lib/active_support/callbacks.rb:81:在`run_callbacks'中
  actionpack (3.2.8) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
  actionpack (3.2.8) lib/action_dispatch/middleware/remote_ip.rb:31:in`调用'
  actionpack (3.2.8) lib/action_dispatch/middleware/debug_exceptions.rb:16:in`调用'
  actionpack (3.2.8) lib/action_dispatch/middleware/show_exceptions.rb:56:in`调用'
  railties (3.2.8) lib/rails/rack/logger.rb:26:in `call_app'
  railties (3.2.8) lib/rails/rack/logger.rb:16:in `调用'
  actionpack (3.2.8) lib/action_dispatch/middleware/request_id.rb:22:in`调用'
  rack (1.4.1) lib/rack/methodoverride.rb:21:in`调用'
  rack (1.4.1) lib/rack/runtime.rb:17:in`调用'
  activesupport (3.2.8) lib/active_support/cache/strategy/local_cache.rb:72:in`调用'
  机架(1.4.1)lib/rack/lock.rb:15:in`调用'
  actionpack (3.2.8) lib/action_dispatch/middleware/static.rb:62:in`调用'
  机架缓存 (1.2) lib/rack/cache/context.rb:136:in `前进'
  机架缓存 (1.2) lib/rack/cache/context.rb:245:in `fetch'
  机架缓存 (1.2) lib/rack/cache/context.rb:185:in `lookup'
  rack-cache (1.2) lib/rack/cache/context.rb:66:in`调用!'
  机架缓存 (1.2) lib/rack/cache/context.rb:51:in `调用'
  railties (3.2.8) lib/rails/engine.rb:479:in `调用'
  railties (3.2.8) lib/rails/application.rb:223:in `调用'
  railties (3.2.8) lib/rails/railtie/configurable.rb:30:in `method_missing'
  rack-pjax (0.6.0) lib/rack/pjax.rb:12:in `调用'
  乘客(3.0.17)lib/phusion_passenger/rack/request_handler.rb:96:in`process_request'
  乘客(3.0.17)lib/phusion_passenger/abstract_request_handler.rb:516:in`accept_and_process_next_request'
  乘客(3.0.17)lib/phusion_passenger/abstract_request_handler.rb:274:在“main_loop”中
  乘客(3.0.17)lib/phusion_passenger/rack/application_spawner.rb:206:in`start_request_handler'
  乘客(3.0.17)lib/phusion_passenger/rack/application_spawner.rb:171:in`block in handle_spawn_application'
  乘客(3.0.17)lib/phusion_passenger/utils.rb:470:in`safe_fork'
  乘客(3.0.17)lib/phusion_passenger/rack/application_spawner.rb:166:in`handle_spawn_application'
  乘客(3.0.17)lib/phusion_passenger/abstract_server.rb:357:in`server_main_loop'
  乘客(3.0.17)lib/phusion_passenger/abstract_server.rb:206:in`start_synchronously'
  乘客(3.0.17)lib/phusion_passenger/abstract_server.rb:180:in`启动'
  乘客(3.0.17)lib / phusion_passenger / rack / application_spawner.rb:129:在“启动”
  乘客(3.0.17)lib/phusion_passenger/spawn_manager.rb:253:in`块(2 个级别)在 spawn_rack_application 中'
  乘客(3.0.17)lib/phusion_passenger/abstract_server_collection.rb:132:in`lookup_or_add'
  乘客(3.0.17)lib/phusion_passenger/spawn_manager.rb:246:in`在spawn_rack_application中阻止'
  乘客(3.0.17)lib/phusion_passenger/abstract_server_collection.rb:82:in`同步中的阻止'
  :10:在`同步'中
  乘客(3.0.17)lib/phusion_passenger/abstract_server_collection.rb:79:in`同步'
  乘客(3.0.17)lib/phusion_passenger/spawn_manager.rb:244:in`spawn_rack_application'
  乘客(3.0.17)lib/phusion_passenger/spawn_manager.rb:137:in`spawn_application'
  乘客(3.0.17)lib/phusion_passenger/spawn_manager.rb:275:in`handle_spawn_application'
  乘客(3.0.17)lib/phusion_passenger/abstract_server.rb:357:in`server_main_loop'
  乘客(3.0.17)lib/phusion_passenger/abstract_server.rb:206:in`start_synchronously'
  乘客(3.0.17)辅助脚本/乘客生成服务器:99:在''

数据库.yml:

生产:
  适配器:mysql2
  编码:utf8
  数据库: [db]
  主持人:[主持人]
  池:5
  用户名:[用户]
  密码:[密码]
  超时:2000

我正在运行 Ubuntu 12.04.1 LTS、Ruby 1.9.3p194(通过 RVM)和 Passenger 3.0.18。

在 WEBrick 下的开发模式下我从未遇到过这个问题。

答案1

我在使用 ruby​​ 2.0.0-p0 时遇到了同样的问题。

../bundle/ruby/2.0.0/gems/activerecord-3.2.13/lib/active_record/connection_adapters/mysql2_adapter.rb:73:in `ping'

我尝试过 unicorn、thin 和 pilot。这并没有改变任何东西。

production:
  adapter: mysql2
  database: ***
  username: ***
  password: ***
  host: an IP
  reconnect: true
  wait_timeout: 3 # I've tried with this option and without

有任何想法吗 ?

libmysqlclient 5.1.66-0+squeeze1
mysql-server 5.1.66-0+squeeze1

编辑

这似乎是一个防火墙问题具有 TCP Keepalive。如果 MySQL 客户端的 TCP Keepalive 大于防火墙的 Keepalive,则会出现此问题。

细节 :http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/

答案2

我正在使用 Google Compute Engine,并且一直遇到同样的问题 - 大约 10 分钟的空闲时间后,对我的 Rails 应用程序的请求就会完全挂起,没有明显的日志或问题出现的迹象。

经过多次调试和跟踪,结果发现是防火墙超时——来自 GCE 实例的 TCP 连接在空闲 10 分钟后自动超时。我成功地解决了这个问题,方法是将 TCP keepalive 配置为在空闲 60 秒(而不是默认的 2 小时)时发送其第一个探测,以便与数据库的长寿命 TCP 连接保持活动状态。这里也提到了这一点:https://cloud.google.com/sql/docs/gce-access

# 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

相关内容