Ruby on rails 吃独角兽的记忆

Ruby on rails 吃独角兽的记忆,ruby-on-rails,diskspace,unicorn,Ruby On Rails,Diskspace,Unicorn,我在amazon上有一个m1.small实例,它有8GB的硬盘空间,我的rails应用程序可以在上面运行。它平稳地运行了两周,然后崩溃,表示内存已满。 应用程序运行在rails 3.1.1、unicorn和nginx上 我根本不明白为什么服用13G? 我杀死了独角兽,“free”命令显示了一些可用空间,而df仍然说100% 我重新启动了实例,一切正常。 免费(杀死独角兽之前) df-l(杀死独角兽前) sudo du-hc——最大深度=1(杀死独角兽之前) 自由(杀死独角兽后) df-l(杀死独

我在amazon上有一个m1.small实例,它有8GB的硬盘空间,我的rails应用程序可以在上面运行。它平稳地运行了两周,然后崩溃,表示内存已满。 应用程序运行在rails 3.1.1、unicorn和nginx上

我根本不明白为什么服用13G?
我杀死了独角兽,“free”命令显示了一些可用空间,而df仍然说100%
我重新启动了实例,一切正常。

免费(杀死独角兽之前) df-l(杀死独角兽前) sudo du-hc——最大深度=1(杀死独角兽之前) 自由(杀死独角兽后) df-l(杀死独角兽后) 独角兽
你可以设置监视你的独角兽工作人员,如果他们消耗了太多内存,就杀死他们。然后,Unicorn主进程将分叉另一个工作进程来替换此工作进程。问题解决了。:-)

我认为你把内存使用和磁盘空间使用混为一谈了。看起来独角兽和它的孩子们使用了大约500 MB的内存,你看第二个“-/+buffers/cache:”数字可以看到真正的可用内存。就磁盘空间而言,我赌的是某种类型的日志文件或类似的东西。您应该在数据目录中执行du-h,以了解到底是什么在使用如此多的存储空间。最后一个建议是,一个鲜为人知的事实是,如果Ruby分配内存,它永远不会将内存返回给操作系统。它仍然在内部使用它,但是一旦Ruby获取了一些内存,让它将未使用的内存返回操作系统的唯一方法就是退出这个过程。例如,如果您碰巧有一个进程将内存使用量增加到500 MB,那么即使在请求完成并且GC循环运行之后,您也无法再次使用该500 MB。然而,Ruby将为将来的请求重用分配的内存,因此它不太可能进一步增长


最后,Sergei提到上帝监控内存进程。如果您有兴趣使用它,那么已经有一个很好的配置文件。请务必阅读,因为unicorn配置文件中有一些关键的东西,这是上帝配置假定的。

正如普雷斯顿提到的,您没有内存问题(超过40%的可用空间),您有磁盘满的问题。du报告大多数存储在/root/data中消耗

您可以使用find来识别非常大的文件,例如,下面将显示该目录下大小大于100MB的所有文件

sudo find /root/data -size +100M
如果unicorn仍在运行,lsof(列出打开的文件)可以显示正在运行的程序或一组特定进程正在使用哪些文件(-p PID),例如:

将显示您打开的文件大小大于100MB

我刚刚发布了“”gem。这使您能够根据1)最大请求数和2)进程内存大小(RSS)杀死Unicorn worker,而不会影响请求

它真的很容易使用。不需要外部工具。首先,请将此行添加到您的
GEM文件中

gem 'unicorn-worker-killer'
然后,请将以下行添加到
config.ru

# Unicorn self-process killer
require 'unicorn/worker_killer'

# Max requests per worker
use Unicorn::WorkerKiller::MaxRequests, 10240 + Random.rand(10240)

# Max memory size (RSS) per worker
use Unicorn::WorkerKiller::Oom, (96 + Random.rand(32)) * 1024**2

强烈建议随机设置阈值,以避免一次杀死所有工作人员。

如果您正在使用newrelic,请尝试删除应用程序中的newrelic。Newrelic rpm gem本身正在泄漏内存。我也有同样的问题,我绞尽脑汁花了将近10天的时间来解决这个问题

希望这对你有帮助

我联系了newrelic支持团队,下面是他们的回复

感谢联系支持部门。我对这令人沮丧的事情深表歉意 你有过的经验。作为一种性能监控工具,我们的 意图是“先不伤害”,我们非常重视这类问题 真的

我们最近确定了该问题的原因,并发布了 补丁来解决它。(见附件)。我们 希望你能考虑用这个新的修复来恢复监控。 如果您有兴趣这样做,请确保您至少使用了 v3.6.8.168从现在开始

如果您有任何其他问题或顾虑,请告知我们。 我们渴望解决这些问题

即使我尝试更新newrelic gem,但它仍然会泄漏内存。最后,我必须删除rewrelic,尽管它是一个很棒的工具,但我们不能以这样的代价使用它(内存泄漏)


希望这能对你有所帮助。

那么你说如果没有人监控,独角兽会继续吃memmory?谢谢sergei的快速回复。@KrishnaprasadVarma我是说可能会发生泄漏。您的代码可能会泄漏,或者ruby本身,或者某些第三方gem。调试这些可以是。。。不平凡。停止冒犯的过程,重新开始,要容易得多。谢谢你,普雷特森。我确信不会生成消耗内存的日志。这个周末我会试试上帝或莫妮特。。。这很方便。谢谢,这是给独角兽的。将努力创造彩虹工人杀手在假期!有意思。。谢谢你的宝石。奎师那,如果你对这个宝石有任何问题,请告诉我!
             total       used       free     shared    buffers     cached    
Mem:       1705192     985876     **719316**          0     365536     228576    
-/+ buffers/cache:     391764    1313428    
Swap:       917500      46176     871324  
Filesystem           1K-blocks      Used Available Use% Mounted on  
/dev/xvda1             8256952   7837516         8 100% /  
none                    847464       120    847344   1% /dev  
none                    852596         0    852596   0% /dev/shm  
none                    852596        56    852540   1% /var/run  
none                    852596         0    852596   0% /var/lock  
/dev/xvda2           153899044    192068 145889352   1% /mnt  
/dev/xvdf             51606140  10276704  38707996  21% /data  
rails_env = 'production'  

working_directory "/home/user/app_name"  
worker_processes 5  
preload_app true  
timeout 60  

rails_root = "/home/user/app_name"  
listen "#{rails_root}/tmp/sockets/unicorn.sock", :backlog => 2048  
# listen 3000, :tcp_nopush => false  

pid "#{rails_root}/tmp/pids/unicorn.pid"  
stderr_path "#{rails_root}/log/unicorn/unicorn.err.log"  
stdout_path "#{rails_root}/log/unicorn/unicorn.out.log"  

GC.copy_on_write_friendly = true if GC.respond_to?(:copy_on_write_friendly=)  

before_fork do |server, worker|  
  ActiveRecord::Base.connection.disconnect!  

  ##  
  # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and  
  # immediately start loading up a new version of itself (loaded with a new  
  # version of our app). When this new Unicorn is completely loaded  
  # it will begin spawning workers. The first worker spawned will check to  
  # see if an .oldbin pidfile exists. If so, this means we've just booted up  
  # a new Unicorn and need to tell the old one that it can now die. To do so  
  # we send it a QUIT.  
  #  
  # Using this method we get 0 downtime deploys.  

  old_pid = "#{rails_root}/tmp/pids/unicorn.pid.oldbin"  
  if File.exists?(old_pid) && server.pid != old_pid  
    begin  
      Process.kill("QUIT", File.read(old_pid).to_i)  
    rescue Errno::ENOENT, Errno::ESRCH  
      # someone else did our job for us  
    end  
  end  
end  


after_fork do |server, worker|  
  ActiveRecord::Base.establish_connection  
  worker.user('rails', 'rails') if Process.euid == 0 && rails_env == 'production'  
end  
sudo find /root/data -size +100M
sudo lsof | awk  '$5 ~/REG/ && $7 > 100000000 { print }'
gem 'unicorn-worker-killer'
# Unicorn self-process killer
require 'unicorn/worker_killer'

# Max requests per worker
use Unicorn::WorkerKiller::MaxRequests, 10240 + Random.rand(10240)

# Max memory size (RSS) per worker
use Unicorn::WorkerKiller::Oom, (96 + Random.rand(32)) * 1024**2