Ruby on rails 吃独角兽的记忆
我在amazon上有一个m1.small实例,它有8GB的硬盘空间,我的rails应用程序可以在上面运行。它平稳地运行了两周,然后崩溃,表示内存已满。 应用程序运行在rails 3.1.1、unicorn和nginx上 我根本不明白为什么服用13G?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(杀死独
我杀死了独角兽,“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