一、什么是God
God 是用 Ruby 寫的進程監控框架,具有易配置易擴展的優點。用它可以很方便的監控一個軟件的運行狀態,并在特定的條件下殺死或重啟進程,以保證任務的持久性和高可用性。
常見場景
- 監控一個進程,當它因意味錯誤退出或失去響應時重新啟動它。
- 監控一個進程,當它耗費的CPU或內存超過特定值時殺死或重新啟動它。
二、God的優缺點
優點:
- 啟動和控制都使用一個命令: god
- 可以管理daemon和非daemon進程
- 可以設置進程的uid、env、dir、log等參數
- 進程配置文件和supervisord類似,但使用ruby的語法。支持類似monit的,對進程使用資源和各種條件的控制
- 支持進程配置動態加載功能
- 支持把多個進程配置拆分成單獨的配置文件,類似include功能
- 支持通知功能,包括:Webhook、Email、Twitter、Jabber、Campfire等多個接口
- 根據PID的方式進行監控,GOD可以隨便升級和重啟
缺點
- 不提供web端和rpc接口
- log查看stdrr/stdout 功能似乎不能正常work,不過我基本上用不到這個功能
- linux下采用2種方式檢測進程poll和event。root默認啟用event模式,如果啟動的進程錯誤,它會注冊一個proc_exit事件,但無法響應。
三、安裝
最好的方法是通過rubygems安裝:
$[sudo] gem install god
四、快速開始
新建一個目錄,然后寫一個簡單的服務器腳本。讓我們給它命名為simple.rb:
新建一個目錄,然后寫一個簡單的服務器腳本。讓我們給它命名為simple.rb
:
loop do
puts 'Hello'
sleep 1
end
現在我們將寫一個god配置文件,告訴god關于我們的進程。把它和simple.rb
放在同一個文件夾,命名為simple.god
:
God.watch do |w|
w.name = "simple"
w.start = "ruby /full/path/to/simple.rb"
w.keepalive
end
這是最簡單的god配置文件。
我們以宣布一個God.watch塊開始。
一個watch在god里代表一個我們想要watch和控制的進程。
每個watch必須有一個唯一的名字和一個告訴god怎么啟動進程的命令。
keepalive的聲明告訴god保持這個進程alive。
假如god啟動時這個進程沒有運行,god將會啟動它。假如進程不響應,god就會重新啟動它。
在這個例子里,simple進程在前端運行,所以god會照看該進程,保持跟蹤這個進程的PID。
如果可能,最好要god為我們啟動進程,這樣我們就不必擔心指定和保持跟蹤PID的文件。
后面我們將看見不能在前景運行或者需要指定進程PID的情況下怎樣管理。
為了運行god,我們使用參數-c給它提供一個參數。通過參數-D就可以讓god在前端運行,能讓我們看見發生了什么。
$ god -c path/to/simple.god -D
god可以通過兩種方式來監控你的進程。
第一個和最好的一個是方法是用event。
不是每個系統都支持,但是如果系統支持的話會自動使用event。
通過event,god會立即知道一個進程是否存在。
對那些系統沒有event支持的,god使用polling機制。這個部分的整個輸出如下:
# Events
I [2011-12-10 15:24:34] INFO: Loading simple.god
I [2011-12-10 15:24:34] INFO: Syslog enabled.
I [2011-12-10 15:24:34] INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-10 15:24:34] INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-10 15:24:34] INFO: simple move 'unmonitored' to 'init'
I [2011-12-10 15:24:34] INFO: simple moved 'unmonitored' to 'init'
I [2011-12-10 15:24:34] INFO: simple [trigger] process is not running (ProcessRunning)
I [2011-12-10 15:24:34] INFO: simple move 'init' to 'start'
I [2011-12-10 15:24:34] INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-10 15:24:34] INFO: simple moved 'init' to 'start'
I [2011-12-10 15:24:34] INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:24:34] INFO: simple move 'start' to 'up'
I [2011-12-10 15:24:34] INFO: simple registered 'proc_exit' event for pid 23298
I [2011-12-10 15:24:34] INFO: simple moved 'start' to 'up'
# Polls
I [2011-12-07 09:40:18] INFO: Loading simple.god
I [2011-12-07 09:40:18] INFO: Syslog enabled.
I [2011-12-07 09:40:18] INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-07 09:40:18] INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-07 09:40:18] INFO: simple move 'unmonitored' to 'up'
I [2011-12-07 09:40:18] INFO: simple moved 'unmonitored' to 'up'
I [2011-12-07 09:40:18] INFO: simple [trigger] process is not running (ProcessRunning)
I [2011-12-07 09:40:18] INFO: simple move 'up' to 'start'
I [2011-12-07 09:40:18] INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-07 09:40:19] INFO: simple moved 'up' to 'up'
I [2011-12-07 09:40:19] INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:40:24] INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:40:29] INFO: simple [ok] process is running (ProcessRunning)
你可以看見god啟動了,注意到simple沒有在運行,啟動它,然后每隔5分鐘檢查一下確保simple運行正常。
假如你想看見god的魔力,kill simple的進程。你會發現類似如下的輸出:
# Events
I [2011-12-10 15:33:38] INFO: simple [trigger] process 23416 exited (ProcessExits)
I [2011-12-10 15:33:38] INFO: simple move 'up' to 'start'
I [2011-12-10 15:33:38] INFO: simple deregistered 'proc_exit' event for pid 23416
I [2011-12-10 15:33:38] INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-10 15:33:38] INFO: simple moved 'up' to 'start'
I [2011-12-10 15:33:38] INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:33:38] INFO: simple move 'start' to 'up'
I [2011-12-10 15:33:38] INFO: simple registered 'proc_exit' event for pid 23601
I [2011-12-10 15:33:38] INFO: simple moved 'start' to 'up'
# Polls
I [2011-12-07 09:54:59] INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:55:04] INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:55:09] INFO: simple [trigger] process is not running (ProcessRunning)
I [2011-12-07 09:55:09] INFO: simple move 'up' to 'start'
I [2011-12-07 09:55:09] INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-07 09:55:09] INFO: simple moved 'up' to 'up'
I [2011-12-07 09:55:09] INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:55:14] INFO: simple [ok] process is running (ProcessRunning)
保持進程啟動是好的,但是假如能夠保證我們的進程表現良好,當資源超過我們的設置,重新啟動進程將更好。通過添加一點條件,當內存或者CPU超過我們設定的限制,我們能夠容易地讓我們的進程重啟。編輯simple.god配置文件如下:
God.watch do |w|
w.name = 'simple'
w.start = "ruby /full/path/to/simple.rb"
w.keepalive( :memory_max => 150.megabytes,
:cpu_max => 50.percent)
end
這里我在keepalive命令中使用了 :memory_max
選項。
現在,假如進程的內存用量超過150M, god就會重啟他。
相似地,通過設置 :cpu_max
, 假如CPU的使用超過50%,god也會重啟它。
默認這些屬性每隔30
秒檢查一次,假如五個條件中滿足三個,則會執行。這防止了進程因為暫時的資源峰值導致重啟。
為了測試這個特性,修改你的simple.rb服務器腳本使得引起內存泄露:
data = ''
loop do
puts 'Hello'
100000.times { data << 'x' }
end
按Ctrl-C結束god。注意到你的simple進程依然在運行。
用剛才的方式再次啟動god。
現在代替了啟動simple進程,god監測到simple運行,簡單的切換到up狀態。
# Events
I [2011-12-10 15:36:00] INFO: Loading simple.god
I [2011-12-10 15:36:00] INFO: Syslog enabled.
I [2011-12-10 15:36:00] INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-10 15:36:00] INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-10 15:36:00] INFO: simple move 'unmonitored' to 'init'
I [2011-12-10 15:36:00] INFO: simple moved 'unmonitored' to 'init'
I [2011-12-10 15:36:00] INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:36:00] INFO: simple move 'init' to 'up'
I [2011-12-10 15:36:00] INFO: simple registered 'proc_exit' event for pid 23601
I [2011-12-10 15:36:00] INFO: simple moved 'init' to 'up'
# Polls
I [2011-12-07 14:50:46] INFO: Loading simple.god
I [2011-12-07 14:50:46] INFO: Syslog enabled.
I [2011-12-07 14:50:46] INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-07 14:50:47] INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-07 14:50:47] INFO: simple move 'unmonitored' to 'up'
I [2011-12-07 14:50:47] INFO: simple moved 'unmonitored' to 'up'
I [2011-12-07 14:50:47] INFO: simple [ok] process is running (ProcessRunning)
為了讓我們的simple服務運行,我們重新啟動simple,這里必須強烈地要求重啟否則新添加的配置不會生效
god restart simple
通過日志你可以看見god結束了simple進程并重新啟動了:
# Events
I [2011-12-10 15:38:13] INFO: simple move 'up' to 'restart'
I [2011-12-10 15:38:13] INFO: simple deregistered 'proc_exit' event for pid 23601
I [2011-12-10 15:38:13] INFO: simple stop: default lambda killer
I [2011-12-10 15:38:13] INFO: simple sent SIGTERM
I [2011-12-10 15:38:14] INFO: simple process stopped
I [2011-12-10 15:38:14] INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-10 15:38:14] INFO: simple moved 'up' to 'restart'
I [2011-12-10 15:38:14] INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:38:14] INFO: simple move 'restart' to 'up'
I [2011-12-10 15:38:14] INFO: simple registered 'proc_exit' event for pid 23707
I [2011-12-10 15:38:14] INFO: simple moved 'restart' to 'up'
# Polls
I [2011-12-07 14:51:13] INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:51:13] INFO: simple move 'up' to 'restart'
I [2011-12-07 14:51:13] INFO: simple stop: default lambda killer
I [2011-12-07 14:51:13] INFO: simple sent SIGTERM
I [2011-12-07 14:51:14] INFO: simple process stopped
I [2011-12-07 14:51:14] INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-07 14:51:14] INFO: simple moved 'up' to 'up'
I [2011-12-07 14:51:14] INFO: simple [ok] process is running (ProcessRunning)
God現在開始報告內存和CPU的使用情況
# Events and Polls
I [2011-12-07 14:54:37] INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:37] INFO: simple [ok] memory within bounds [2032kb] (MemoryUsage)
I [2011-12-07 14:54:37] INFO: simple [ok] cpu within bounds [0.0%%] (CpuUsage)
I [2011-12-07 14:54:42] INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:42] INFO: simple [ok] memory within bounds [2032kb, 13492kb] (MemoryUsage)
I [2011-12-07 14:54:42] INFO: simple [ok] cpu within bounds [0.0%%, *99.7%%] (CpuUsage)
I [2011-12-07 14:54:47] INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:47] INFO: simple [ok] memory within bounds [2032kb, 13492kb, 25568kb] (MemoryUsage)
I [2011-12-07 14:54:47] INFO: simple [ok] cpu within bounds [0.0%%, *99.7%%, *100.0%%] (CpuUsage)
I [2011-12-07 14:54:52] INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:52] INFO: simple [ok] memory within bounds [2032kb, 13492kb, 25568kb, 37556kb] (MemoryUsage)
I [2011-12-07 14:54:52] INFO: simple [trigger] cpu out of bounds [0.0%%, *99.7%%, *100.0%%, *98.4%%] (CpuUsage)
I [2011-12-07 14:54:52] INFO: simple move 'up' to 'restart
在最后的一行,你能看見CPU的用量已經超過了50%三次了,
god重新啟動了進程。god會持續地監測simple進程,只要god在運行,進程就會被一直監控。
現在,你結束god之前,讓我們先通過god結束simple服務。在一個新的終端,輸入以下命令:
god stop simple
如果想停止god,你可以自由地Ctrl-C 退出god 了。
不過這只是個開始。在實際應用中,keepalive 命令是一個方便的方法,使用了可以直接使用的更高級的事務和條件構造。你可以配置許多不同的條件,當CPU或者內存使用太多,磁盤超過下限,當一個指定的URL返回錯誤代碼,等等。另外,你可以寫自己的自定義條件,然后在配置文件里使用它。伴隨著復雜的和可擴展的通知體系,可以控制許多不同的生命周期。
既然你已經知道怎么使用god,讓我們看看god更強大的一面吧。再說一次,最好的學習方法是通過示例。下面這個配置文件是我在gravatar.com保證mongrels運行使用的配置文件。
## 在這里我設置了一個常量,用于整個文件。保持RAILS_ROOT的值是一個常量使得腳本很容易適合其他應用
RAILS_ROOT = "/Users/tom/dev/gravatar2"
## 循環監控 8200 8210 8202 端口
%w{8200 8201 8202}.each do |port|
God.watch do |w|
w.name = "gravatar2-mongrel-#{port}"
## 使用 mogrel_rails 命令啟動
w.start = "mogrel_rails start -c #{RAILS_ROOT} -p #{port} \
-P #{RAILS_ROOT}/log.mogrel.#{port}.pid -d"
## 使用 mogrel_rails 命令停止
w.stop = "morgrel_rails stop -P #{RAILS_ROOT}/log/mogrel.#{port}.pid"
## 重啟
w.restart = "mongrel_rails restart -P #{RAILS_ROOT}/log/mogrel.#{port}.pid"
w.pid_file = File.join(RAILS_ROOT, "log/mogrel.#{port}.pid")
## 假如你正監視的進程是一個后天進程(我的也是),你需要設置pid_file屬性。????
## behavio允許你伴隨著start/stop/restart執行額外的命令。
## 在我們的例子里,假如進程死了,它會留下PID文件。
## 假如下次重新啟動這個程序,就會啟動失敗,提示PID文件已經存在。
## 所以啟動程序時,我們想先清除PID文件。內建的clean_pid_file就會清除
w.behavior(:clean_pid_file)
## watch包含由可執行的動作組成的條件應該返回true
w.start_if do |start|
start.condition(:process_running) do |c|
## 通過用一個識別字符調用condition條件來描述condition,這個例子中是:process_running. 每個條件描述一個poll間隔,這個間隔將覆蓋默認的間隔。這個例子中,我想要每個5秒鐘檢查一次進程,而不是像其他condition一樣用30秒間隔
c.inteval = 5.seconds
c.running = false
end
end
## 和start_if類似,restart_if命令組合condition,
## 然后觸發restart。memory_usage條件將會失敗,
## 假如指定的進程使用了太多的內存。
## 最大允許的內存通過above屬性來指定(你可以用kilobytes, megabytes, 或者gibabytes助手)。
## 為了觸發restart需要觸發的次數通過times設置。
## 這個可以是一個整數,也可以是一個數組。
## 整數意味著它必須連續失敗許多次而數組[x, y]意味著必須y次中失敗x次。
w.restart_if do |restart|
restart.condition(:memory_usage) do |c|
c.above = 150.megabytes
c.times = [3, 5] # 3 out of 5 intevals
end
restart.condition(:cpu_usage) do |c|
c.above = 50.percent
c.times = 5
end
end
#lifecycle
## 在lifecycle部分中的condition只要進程被監視就一直活動(它們通過狀態的改變活動)。
## :flapping condition守護除了god快速開始和重啟你的應用的這些邊緣的狀態的其他情況。
## 比如服務器配置變化或者外部服務的不可用都可能造成我得進程不能啟動。
## 那樣的話,god將會一直重試啟動我的進程。
## :flapping condition提供了兩個水平的放棄不穩定進程。
## 假如我翻譯以上的option代碼,那就是:
## 假如watch在5分鐘里被啟動或者重啟了5次,然后不再監視它。。。
## 然后10分鐘后,再次監視他看看是否只是一個臨時的問題;
## 假如進程在兩小時里依然不穩定,然后徹底放棄監視
## lifecycle 是一個非常重要的配置,之前聽過架構師說過,God 進程怎么一直在重啟
## 肯定就是這里的坑!!!!!!!
w.lifecycle do |on|
on.condition(:flapping) do |c|
c.to_state = [:start, :restart]
c.times = 5
c.within = 5.minute
c.transition = :unmonitored
c.retry_in = 10.minutes
c.retry_times = 5
c.retry_within = 2.hours
end
end
end
end
五、動態加載文件進入一個已經運行的god
God允許你加載或者重新加載配置文件進入一個已經運行的實例。當你準備這樣做得時候,有幾件事情需要考慮:
- 已經存在的watch會被新配置文件里的同名的watch覆蓋
- 所有的路徑必須是絕對路徑或者god運行的相對路徑
將配置文件加載至一個正在運行的god,運行以下命令:
sudo god load path/to/config.god
動態加載的配置文件可以包含任何一個普通的配置文件,然而,全局變量例如God.pid_file_directory塊將可能會被忽視(會在日志里產生一個警告)。
如果把god作為一個后臺進程,只需要把配置文件的路徑傳遞給god(你需要使用sudo假如你在linux使用event或者想要使用setuid/setgid)
sudo god -c /path/to/config.god
當你寫配置文件的時候,在前臺運行god這樣你能看見log消息,可能會很有幫助。你可以:
sudo god -c /path/to/config.god -D
你能啟動、重啟、停止、監測、不監測你的watch用同樣的工具像這樣:
sudo god stop gravatar2-mongrel-8200
六、God 的其他功能
+ 重定向你進程的STDOUT和STDERR
+ 改變進程的UID/GID
+ 設置工作目錄
+ 設置環境變量
+ 使用CHROOT改變文件系統的根目錄
+ Lambda命令
+ 自定義默認的停止運行lambda
+ 加載其他配置文件
+ 為單個watch得到日志文件
+ 通知
轉載,有修改。原文God 使用手冊