Unicorn Memory Usage füllt fast den gesamten Arbeitsspeicher aus
Hier gibt es im Wesentlichen drei Probleme:
1) Unicorn scheint den gesamten Arbeitsspeicher stetig zu füllen, sodass ich die Mitarbeiter manuell entfernen muss.
2) Einhorn scheint aus irgendeinem Grund zusätzliche Arbeiter hervorzubringen, obwohl ich eine feste Anzahl von Arbeitern angegeben habe (7 von ihnen). Dies hat teilweise zur Folge, dass sich der Arbeitsspeicher aufbaut und ich die Mitarbeiter manuell entferne.
3) Die Bereitstellung ohne Ausfallzeiten ist in meinem Fall unzuverlässig. Manchmal werden die Änderungen übernommen, manchmal treten Gateway-Timeouts auf. Jeder Einsatz wird zu einer sehr stressigen Situation.
Ich mag es nicht wirklich, Monit zu verwenden, weil es Arbeiter tötet, ohne darauf zu warten, dass die Arbeiter ihre Anfragen erledigen.
Also ist das normal? Haben andere Benutzer, die Unicorn verwenden, das gleiche Problem, wenn der Arbeitsspeicher unkontrolliert wächst?
Und auch wo Arbeiter die Anzahl der entstehenden Arbeiter nicht der definierten Anzahl der Arbeiter entspricht?
Die andere Alternative ist der Einhornkiller, den ich nach dem Lesen ausprobieren würdeEinhorn, das Gedächtnis isst.
Kleines Update:
So kam es zu einem Punkt, an dem New Relic mir mitteilte, dass das Gedächtnis fast 95% betrug. Also musste ich einen Arbeiter töten. Interessanterweise hat das Töten dieses Arbeiters die Erinnerung um einiges verringert, wie aus der folgenden Grafik ersichtlich ist.
Was ist damit?
Als Referenz hier ist meineunicorn.rb
undunicorn_init.sh
. Würde es lieben, wenn mir jemand sagt, dass irgendwo ein Fehler vorliegt.
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 do |_|
ENV["BUNDLE_GEMFILE"] = '/home/deployer/apps/myapp/current/Gemfile'
end
before_fork do |server, worker|
# Disconnect since the database connection will not carry over
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 do |server, worker|
# Start up the database connection again in the 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 to change any of the following variables for your 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" ]; then
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
then
n=$TIMEOUT
while test -s $OLD_PIN && test $n -ge 0
do
printf '.' && sleep 1 && n=$(( $n - 1 ))
done
echo
if test $n -lt 0 && test -s $OLD_PIN
then
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