Я запускаю сайт 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