Comment surveiller les passagers nginx avec un monit

J’ai plusieurs applications de rails déployées par nginx passagers. Je veux que ces applications soient surveillées en utilisant monit. Comment puis-je surveiller ces applications en utilisant monit? Dois-je aussi surveiller nginx?

C’est comme ça que j’ai résolu ce problème. Tout d’abord, j’ai ajouté à application.rb:

# Monit support if defined?(PhusionPassenger) require 'pidfile_manager' PhusionPassenger.on_event(:starting_worker_process) do |forked| if forked # We're in smart spawning mode. PidfileManager.write_pid_file else # We're in conservative spawning mode. We don't need to do anything. end end PhusionPassenger.on_event(:stopping_worker_process) do PidfileManager.remove_pid_file end end 

et puis j’ai implémenté le PidfileManager:

 module PidfileManager extend self BASENAME = '/var/tmp/rack.*.pid' def write_pid_file pid = Process.pid count = 1 pidfile = nil go_over_pid_files do |file, saved_pid| file_id = file[/(\d+)/,1].to_i # Increase counter only if we met the same file id count += 1 if file_id == count # We're already there return if saved_pid == pid # Check if the process is alive res = begin Process.kill(0, saved_pid) rescue Errno::ESRCH nil end # It's dead, reuse unless res pidfile = file break end end pidfile ||= BASENAME.sub('*', count.to_s) File.open(pidfile, 'w') {|f| f.write(pid.to_s)} end def remove_pid_file pid = Process.pid go_over_pid_files do |file, saved_pid| if pid == saved_pid File.unlink(file) break end end end private def go_over_pid_files Dir[BASENAME].each do |file| saved_pid = File.read(file).to_i yield file, saved_pid end end end 

Et puis vous dites simplement à monit de surveiller chaque instance en utilisant /var/tmp/rack.X.pid en tant que pidfile.

Je ne sais pas si c’est trop tard pour poster ceci mais c’est comme ça que j’utilise monit (5.14) pour arrêter les applications de rails passagers qui consumnt trop de mémoire:

monit:

 check program ourapp_live with path "/usr/local/bin/check_passenger_mem_usage ourapp 500" as "ourappuser" if status != 0 then alert if status != 0 then restart start program = "/bin/touch /var/www/vhosts/ourapp/railsapp/current/tmp/restart.txt" stop program = "/bin/true" 

Le script shell vérifie les appels (check_passenger_mem_usage):

 #!/bin/bash # # USER=$1 TRIGGER=$2 if [ -z $USER ] || [ -z $TRIGGER ] then echo "missing args" echo "usage:" echo " check_passenger_mem_usage username alert_threshold" echo echo "(alert_threshold is in mb)" echo exit 1 fi MAX=`/usr/local/rvm/gems/ruby-1.8.7-p357/wrappers/passenger-memory-stats | grep $USER | awk '{print $2}' | sort -n | tail -1|cut -d. -f1` if [ "$MAX" -gt $TRIGGER ] then echo echo "${USER}: We got a runaway! Gobbling ${MAX} mb" echo exit 1 else echo echo "Max is ${MAX}" exit 0 fi 

Ce n’est probablement pas la meilleure solution car elle redémarre l’application complète de rails, mais au moins elle empêche les rails de consumr de grandes quantités de mémoire si l’application consum de la mémoire de temps en temps.

Si vous cherchez à les faire fonctionner et à les faire redémarrer en cas d’erreur, vous pouvez mieux regarder supervisord . Au lieu d’interroger pour savoir si un processus est en cours d’exécution, supervisord exécute réellement le processus lui-même. Les démons qu’il exécute doivent fonctionner au premier plan pour que cela fonctionne, mais ils sont très efficaces et permettront d’accélérer les services beaucoup plus rapidement (monit surveille généralement chaque minute, alors que supervisord verrait la fin du processus et le redémarrerait instantanément).

Nous utilisons supervisord in production pour exécuter tous nos démons (nginx, beanstalkd, memcached, divers services python, etc.), puis nous utilisons monit pour surveiller supervisord en tant que sauvegarde supplémentaire.