我在亚马逊有一个 m1.small 实例,有 8GB 硬盘空间,我的 rails 应用程序在其上运行。它顺利运行了 2 周,然后它崩溃了,说内存已满。
应用程序在 rails 3.1.1、unicorn 和 nginx 上运行

我根本不明白什么是 13G ?
我杀死了 unicorn ,'free' 命令显示了一些可用空间,而 df 仍然说 100%
我重新启动了实例,一切都开始正常工作。

免费(在杀死 unicorn 之前)

             total       used       free     shared    buffers     cached
Mem:       1705192    1671580      33612          0     321816     405288
-/+ buffers/cache:     944476     760716
Swap:       917500      50812     866688

df -l(在杀死 unicorn 之前)
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/xvda1             8256952   7837520         4 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

sudo du -hc --max-depth=1(在杀死 unicorn 之前)
28K ./root
6.6M    ./etc
4.0K    ./opt
9.7G    ./data
1.7G    ./usr
4.0K    ./media
du: cannot access `./proc/27220/task/27220/fd/4': No such file or directory
du: cannot access `./proc/27220/task/27220/fdinfo/4': No such file or directory
du: cannot access `./proc/27220/fd/4': No such file or directory
du: cannot access `./proc/27220/fdinfo/4': No such file or directory
0   ./proc
14M ./boot
120K    ./dev
1.1G    ./home
66M ./lib
4.0K    ./selinux
6.5M    ./sbin
6.5M    ./bin
4.0K    ./srv
148K    ./tmp
16K ./lost+found
20K ./mnt
0   ./sys
253M    ./var
13G .
13G total

免费(杀死 unicorn 后)
             total       used       free     shared    buffers     cached
Mem:       1705192     985876     **719316**          0     365536     228576
-/+ buffers/cache:     391764    1313428
Swap:       917500      46176     871324

df -l(杀死 unicorn 后)
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

unicorn .rb
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

最佳答案

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

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

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

强烈建议随机设置阈值以避免一次杀死所有 worker 。

关于ruby-on-rails - unicorn 吃内存,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8306883/

10-15 22:27