ruby on rails - Unicorn Memory Usage filling up almost all the RAM -
there 3 problems here:
1) unicorn seems steadily filling ram, causing me remove workers manually.
2) unicorn seems spawning additional workers reason, although have specified fixed number of workers (7 of them). partly causing ram buildup, causing me remove workers manually.
3) 0 downtime deployment unreliable in case. picks changes, gateway timeouts. each deploy becomes stressful situation.
i don't using monit, because kills workers without waiting workers finish serving requests.
so, normal? other people deploy using unicorn have same problem ram grows uncontrollably?
and workers number of workers spawned not match number of workers defined?
the other alternative unicorn worker killer, trying out after reading unicorn eating memory.
tiny update:
so came point new relic telling me memory 95%. had kill worker. interestingly, killing worker brought memory down quite lot, seen graph below.
what's that?
for reference, here's unicorn.rb
, unicorn_init.sh
. love tell me there's mistake in there somewhere.
unicorn.rb
root = "/home/deployer/apps/myapp/current" working_directory root pid "#{root}/tmp/pids/unicorn.pid" stderr_path "#{root}/log/unicorn.stderr.log" stdout_path "#{root}/log/unicorn.log" listen "/tmp/unicorn.myapp.sock" worker_processes 7 timeout 30 preload_app true before_exec |_| env["bundle_gemfile"] = '/home/deployer/apps/myapp/current/gemfile' end before_fork |server, worker| # disconnect since database connection not carry on if defined? activerecord::base activerecord::base.connection.disconnect! end old_pid = "#{root}/tmp/pids/unicorn.pid.oldbin`" if old_pid != server.pid begin sig = (worker.nr + 1) >= server.worker_processes ? :quit : :ttou process.kill(sig, file.read(old_pid).to_i) rescue errno::enoent, errno::esrch end end sleep 1 end after_fork |server, worker| # start database connection again in worker if defined?(activerecord::base) activerecord::base.establish_connection end redis.current.quit rails.cache.reconnect end
unicorn_init.sh
#!/bin/sh set -e # feel free change of following variables app: timeout=${timeout-60} app_root=/home/deployer/apps/myapp/current pid=$app_root/tmp/pids/unicorn.pid cmd="cd $app_root; bundle_gemfile=/home/deployer/apps/myapp/current/gemfile bundle exec unicorn -d -c $app_root/config/unicorn.rb -e production" as_user=deployer set -u old_pin="$pid.oldbin" sig () { test -s "$pid" && kill -$1 `cat $pid` } oldsig () { test -s $old_pin && kill -$1 `cat $old_pin` } run () { if [ "$(id -un)" = "$as_user" ]; eval $1 else su -c "$1" - $as_user fi } case "$1" in start) sig 0 && echo >&2 "already running" && exit 0 run "$cmd" ;; stop) sig quit && exit 0 echo >&2 "not running" ;; force-stop) sig term && exit 0 echo >&2 "not running" ;; restart|reload) sig usr2 && echo reloaded ok && exit 0 echo >&2 "couldn't reload, starting '$cmd' instead" run "$cmd" ;; upgrade) if sig usr2 && sleep 2 && sig 0 && oldsig quit n=$timeout while test -s $old_pin && test $n -ge 0 printf '.' && sleep 1 && n=$(( $n - 1 )) done echo if test $n -lt 0 && test -s $old_pin echo >&2 "$old_pin still exists after $timeout seconds" exit 1 fi exit 0 fi echo >&2 "couldn't upgrade, starting '$cmd' instead" run "$cmd" ;; reopen-logs) sig usr1 ;; *) echo >&2 "usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>" exit 1 ;; esac
you appear have 2 problems: 1) have errors in coordination of graceful restart causing old unicorn workers , old master stick around; 2) app (not unicorn) leaking memory.
for former, looking @ before_fork
code, appears you're using memory-constraining approach the example config however, have typo in .oldbin
file name (an extraneous back-tick @ end) means never signal old process because can't read pid non-existent file.
for later, have investigate , drill. in app caching semantics accumulate data on time; examine use of globals, class-vars, , class-instance-vars can retain data references request request. run memory profiles characterize memory use. can mitigate memory leakage killing workers when grow bigger upper limit; unicorn-worker-killer makes easy.
Comments
Post a Comment