Ruby开发中的系统监控、插件与生成器实用指南
1. 用god进行系统监控
1.1 问题提出
在实际开发中,我们常常希望能自动监控所有应用程序。然而,部分应用程序的监控工作颇具挑战性,因为要确保它们正常运行,需要检查诸多方面。这就需要一款能用成熟编程语言进行配置的监控工具,god便是这样一款用Ruby编写的工具。
1.2 安装god
使用以下命令安装god:
$ gem install god
1.3 配置god监控订单导入守护进程
以下是一个监控订单导入守护进程的god配置文件示例:
# god_conf.rb
God.load File.join(File.dirname(__FILE__), 'email_conf.rb')
control_script = '/tmp/order_import_control.rb'
God.watch do |w|
w.name = 'order_import'
w.interval = 60.seconds
w.start = "#{control_script} start"
w.stop = "#{control_script} stop"
w.restart = "#{control_script} restart"
w.start_grace = 10.seconds
w.restart_grace = 10.seconds
w.pid_file = '/tmp/order_import.rb.pid'
w.group = 'server'
w.behavior(:clean_pid_file)
w.start_if do |start|
start.condition(:process_running) do |c|
c.interval = 20.seconds
c.running = false
c.notify = 'admin'
end
end
w.restart_if do |restart|
restart.condition(:memory_usage) do |c|
c.above = 100.megabytes
c.times = [3, 5]
c.notify = 'admin'
end
restart.condition(:cpu_usage) do |c|
c.above = 60.percent
c.times = 5
c.notify = %w(admin boss)
end
end
end
1.4 配置文件解析
- 全局参数设置 :
-
w.name:监控进程的逻辑名称。 -
w.interval:god监控进程的时间间隔。 -
w.start、w.stop、w.restart:分别为启动、停止和重启进程的命令。 -
w.pid_file:进程的PID文件名称。 -
特殊命令
:
w.behavior(:clean_pid_file)表示在进程启动或停止前执行清理PID文件的操作。 -
启动条件
:通过
w.start_if方法定义进程启动的条件,这里检查进程是否正在运行,若未运行则启动。 -
重启条件
:通过
w.restart_if方法定义进程重启的条件,分别检查内存使用和CPU使用率。
1.5 邮件通知配置
邮件通知的配置信息存储在
email_conf.rb
文件中:
# email_conf.rb
God::Contacts::Email.message_settings = {
:from => 'god@example.com'
}
God::Contacts::Email.server_settings = {
:address => 'smtp.example.com',
:port => 25,
:domain => 'example.com',
:authentication => :plain,
:user_name => 'sysadm',
:password => 't0p$ecret'
}
God.contact(:email) do |c|
c.name = 'admin'
c.email = 'admin@example.com'
end
God.contact(:email) do |c|
c.name = 'boss'
c.email = 'boss@example.com'
end
1.6 启动god并查看日志
使用以下命令启动god并查看日志:
mschmidt> god -D -c god_conf.rb
-D
选项表示不将god作为守护进程运行,方便在控制台查看日志输出。启动后,god会检测到订单导入进程未运行并立即启动它,同时持续检查进程的CPU和内存使用情况。
1.7 god与monit的比较
| 工具 | 优点 | 缺点 |
|---|---|---|
| god | 可用Ruby配置,可监控非守护进程脚本 | 不支持Windows,相对monit成熟度和功能稍弱 |
| monit | 更成熟,社区大,有商业支持,功能多 | 不支持Windows |
1.8 god工作流程
graph LR
A[启动god] --> B{进程是否运行}
B -- 否 --> C[启动进程]
B -- 是 --> D{内存使用是否超过100MB}
D -- 是 --> E[重启进程并通知admin]
D -- 否 --> F{CPU使用率是否超过60%}
F -- 是 --> G[重启进程并通知admin和boss]
F -- 否 --> H[继续监控]
C --> H
E --> H
G --> H
2. 创建Rails应用的插件
2.1 问题提出
在开发多个Ruby on Rails应用时,我们会积累大量可复用的代码。但手动复制和调整代码既不方便又容易出错。通过创建自己的插件和生成器,我们可以避免这些问题。
2.2 创建
acts_as_proprietary
插件
使用以下命令创建
acts_as_proprietary
插件:
mschmidt> script/generate plugin acts_as_proprietary
该命令会在
vendor/plugins
目录下创建一个名为
acts_as_proprietary
的子目录,其中包含以下文件:
-
README
:插件说明文件。
-
MIT-LICENSE
:MIT许可证文件。
-
Rakefile
:Rake任务文件。
-
init.rb
:插件初始化文件。
-
install.rb
:插件安装时执行的文件。
-
uninstall.rb
:插件卸载时执行的文件。
-
lib/acts_as_proprietary.rb
:插件的主要代码文件。
-
tasks/acts_as_proprietary_tasks.rake
:插件的任务文件。
-
test/acts_as_proprietary_test.rb
:插件的测试文件。
2.3 实现插件功能
在
lib/acts_as_proprietary.rb
文件中实现添加
dump()
方法到数据库模型的功能:
# lib/acts_as_proprietary.rb
module EnterprisePlugin
module Acts
module Proprietary
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def acts_as_proprietary(options = {})
cattr_accessor :sort_attributes
self.sort_attributes = options[:sort_attributes] || false
include InstanceMethods
extend SingletonMethods
end
end
module InstanceMethods
def dump
result = "Model:#{self.class.name}\n"
keys = attributes.keys
keys.sort! if self.sort_attributes
keys.each { |key| result << "#{key}:#{attributes[key]}\n" }
result
end
end
module SingletonMethods
end
end
end
end
2.4 插件代码解析
- 模块嵌套 :使用三个嵌套的模块声明,为插件代码提供明确的命名空间,避免命名冲突。
-
included()方法 :当模块被包含在其他模块或类中时,该方法会被调用,将ClassMethods模块的方法添加到包含模块或类中。 -
acts_as_proprietary()方法 :接收一个选项哈希,用于控制模型属性在转储前是否排序。 -
dump()方法 :将模型的类名和属性信息转换为文本格式。
2.5 初始化插件
在
init.rb
文件中添加以下代码来初始化插件:
# init.rb
require 'acts_as_proprietary'
ActiveRecord::Base.send(
:include,
EnterprisePlugin::Acts::Proprietary
)
这将加载
acts_as_proprietary
库,并将新功能添加到
ActiveRecord::Base
类中,使其在所有模型类中可用。
2.6 测试插件
创建一个
Customer
模型并测试插件功能:
# db/migrate/20080712165043_create_customers.rb
create_table :customers do |t|
t.string :forename
t.string :surname
t.date :date_of_birth
t.timestamps
end
Customer.create(
:forename => 'John',
:surname => 'Doe',
:date_of_birth => Date.new(1968, 7, 22)
)
# app/models/customer.rb
class Customer < ActiveRecord::Base
acts_as_proprietary :sort_attributes => true
end
在控制台中测试
dump()
方法:
mschmidt> ruby script/console
Loading development environment (Rails 2.1.0)
>> puts Customer.find(1).dump
Model:Customer
created_at:Sat Jul 12 16:57:07 UTC 2008
date_of_birth:1968-07-22
forename:John
id:1
surname:Doe
updated_at:Sat Jul 12 16:57:07 UTC 2008
=> nil
2.7 插件创建流程
graph LR
A[执行创建插件命令] --> B[生成插件目录和文件]
B --> C[编写插件主要代码]
C --> D[编写初始化代码]
D --> E[测试插件功能]
3. 创建Rails应用的生成器
3.1 问题提出
许多企业应用存在通用功能,以往通过复制代码来复用这些功能,不仅操作不便,还容易出错。下面将介绍如何编写一个生成器,自动创建Rails代码,避免代码重复。
3.2 创建带生成器的插件
使用以下命令创建一个名为
acme_monitoring
的插件,并附带生成器:
mschmidt> script/generate plugin acme_monitoring --with-generator
该命令会在
vendor/plugins/acme_monitoring
目录下创建
generators
子目录。为生成器创建一个名为
info_controller
的子目录,以便后续使用
script/generate info_controller
调用生成器。
3.3 编写生成器代码
以下是
info_controller
生成器的代码:
# info_controller_generator.rb
class InfoControllerGenerator < Rails::Generator::Base
def initialize(runtime_args, runtime_options = {})
super
@application_name = args.shift || 'UnknownApplication'
@custom_methods = args || []
end
def manifest
record do |m|
m.template(
'info_controller.rb',
'app/controllers/info_controller.rb',
:collision => :skip,
:assigns => {
:application_name => @application_name,
:custom_methods => @custom_methods
}
)
m.directory 'app/views/info'
@custom_methods.each do |method|
m.template(
'view.html.erb',
"app/views/info/#{method}.html.erb",
:collision => :skip,
:assigns => { :method_name => method }
)
end
end
end
end
3.4 生成器代码解析
-
initialize()方法 :从命令行参数中读取应用程序名称和自定义方法列表。 -
manifest()方法 :返回一个Rails::Generator::Manifest对象,描述要创建的文件和目录。 -
m.template()方法:使用模板文件生成目标文件,可通过:assigns选项传递变量。 -
m.directory()方法:创建目录。
3.5 编写模板文件
3.5.1
info_controller.rb
模板
# info_controller.rb
class InfoController < ApplicationController
def status
application_name = '<%= application_name %>'
status = "Everything's OK with #{application_name}."
render :text => status
end
<% for method in custom_methods %>
<% next if method == 'status' %>
def <%= method %>
# Your code here.
end
<% end %>
end
3.5.2
view.html.erb
模板
# view.html.erb
<%= method_name %>: Your view code here.
3.6 测试生成器
使用以下命令测试
info_controller
生成器:
mschmidt> script/generate info_controller --svn FancyApplication init
生成器会创建
app/controllers/info_controller.rb
和
app/views/info/init.html.erb
文件,并将生成的文件添加到当前的Subversion仓库。生成的
info_controller.rb
文件如下:
# info_controller.rb
class InfoController < ApplicationController
def status
application_name = 'FancyApplication'
status = "Everything's OK with #{application_name}."
render :text => status
end
def init
# Your code here.
end
end
3.7 安装插件
可以将
acme_monitoring
插件代码上传到HTTP服务器、Subversion仓库或Git仓库,然后使用以下命令安装插件:
mschmidt> ./script/plugin install svn://example.com/acme_monitoring
3.8 生成器工作流程
graph LR
A[执行生成器命令] --> B[读取参数]
B --> C[生成控制器文件]
C --> D[创建视图目录]
D --> E{是否有自定义方法}
E -- 是 --> F[生成视图文件]
E -- 否 --> G[结束]
F --> G
3.9 生成器与插件的对比
| 类型 | 用途 | 特点 |
|---|---|---|
| 生成器 | 自动创建Rails代码,避免代码复制 | 可根据参数动态生成文件和目录 |
| 插件 | 为Rails应用添加功能 | 增强Rails的特定部分,如模型、控制器等 |
总结
本文详细介绍了Ruby开发中的系统监控、Rails应用插件和生成器的创建方法。通过使用god工具,可以方便地监控应用程序的运行状态,及时处理异常情况。创建Rails插件和生成器能够有效复用代码,提高开发效率,减少手动操作带来的错误。希望这些方法能帮助开发者更好地进行Ruby on Rails应用开发。
超级会员免费看
842

被折叠的 条评论
为什么被折叠?



