我运行一个处理电子邮件的 ruby on rails 网站 - 电子邮件通过来自 postfix 的 POST 直接转储到 Web 应用程序中。
有时我会收到大量电子邮件,导致 CPU 使用率长时间飙升,这让我的 VPS 提供商对我很不满意,这是可以理解的。这些电子邮件不需要及时处理 - 它们只是需要(最终)得到处理。
显然,我不能仅仅改善这个过程,因为它只查看我的 VPS 上的 CPU 使用情况,而不能考虑其他 VPS 上的 CPU 使用情况。
我找到了一个名为 cpulimit 的实用程序,它可以对特定进程的 CPU 使用率进行严格限制。(例如 20%)。这似乎是实现此目的的理想选择,但我无法将其与 apache/passenger 集成。
Passenger 为每个服务器启动一个 ruby 进程并定期重启它们。每次 pid 都会改变。需要为 Cpulimit 提供一个 pid 编号,以便它能够执行操作。
谁知道我该如何让乘客在启动这个特定的虚拟主机时触发这个命令?
答案1
我不确定这是否是理想的解决方案,但由于缺乏更好的想法,我编写了一个简短的脚本来监控这个并为我调用 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