God教程

一、什么是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 使用手册

参考

God(进程监控)
God进程监控框架
God 使用手册

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,388评论 25 707
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,724评论 6 342
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 原创:liuzesheng 我知道,钻石本质是什么?就是元素碳。和我们做饭的煤球一个元素。 为什么这样贵咧?物以稀...
    liuzesheng阅读 331评论 4 10