Назад | Перейти на главную страницу

Apache / Passenger и cpulimit

Я запускаю сайт ruby ​​on rails, который обрабатывает электронную почту - электронная почта выгружается прямо в веб-приложение через POST из postfix.

Время от времени я могу получить всплеск электронной почты, вызывающий длительный всплеск использования ЦП, из-за чего мой VPS-провайдер недоволен мной. Эти электронные письма не нужно обрабатывать своевременно - их просто нужно (со временем) обработать.

Очевидно, я не могу просто упростить процесс, так как он смотрит только на использование процессора на моем VPS и не может принимать во внимание использование процессора на других VPS.

Я нашел утилиту под названием cpulimit, которая позволит вам установить жесткие ограничения на использование процессора для определенного процесса. (например, 20%). Это кажется идеальным для этой цели, но я не могу интегрироваться с apache / пассажирами.

Passenger запускает рубиновый процесс для каждого сервера и периодически перезапускает их. Каждый раз пид будет меняться. Cpulimit нужно присвоить номер pid, чтобы он действовал.

У кого-нибудь есть идеи, как я могу заставить пассажира запускать вызов этой команды при запуске этого конкретного виртуального хоста?

Я не уверен, что это идеальное решение, но из-за отсутствия лучшей идеи я написал небольшой скрипт, чтобы отслеживать это и вызывать для меня cpulimit.

Я включил его ниже на случай, если он пригодится кому-либо еще.

#!/home/dgs/.rvm/rubies/ruby-1.9.3-p125-perf/bin/ruby

# script to check for mail server processes and enforce a cpulimit on them

# cmd to get the pid of the process you want to limit. 
YOU WOULD NEED TO MAKE THIS RELEVANT TO YOU
CMD='ps -ef | grep mailserver | grep Rack | grep -v grep | awk "{print \$2}"'

# how often to check    
PERIOD = 60

#array to hold list of the currently limitied processes
limiting = []

while true
  processes  = `#{CMD}`.split("\n")

  # iterate thru the newly found processes, limiting any that
  # aren't already being limited
  processes.each do |p|
   if ! limiting.include? p
     system "cpulimit -p #{p} -l 10 -z &"  
     limiting << p
   end 
  end

   # check if any old processes have been killed
   limiting.each do |p|
     begin
       Process.getpgid( p.to_i )
     rescue Errno::ESRCH
       limiting.delete p
     end
   end
   sleep PERIOD
end