当有一些消耗cpu和时间的动作需要执行时,我们就可以使用Gearman来转移负载,尤其对于Web中图片裁剪缩放等操作非常有用,Gearman是一个分布式的运算工具, 支持并行,负载均衡,夸语言,容错等特点,具体介绍看这里
Gearman的设计
Gearman架构
从上面图中可以看出来Gearman的流程为
Client -> Job Server -> Worker
Client为客户端调用,
Job Server为调度器,即gearmand进程
Worker为运算进程
Client和Worker是独立的,客户端锁采用的语言和Worker没有任何关系,比如客户端可以使用ruby,Worker可以采用C来实现
上面这种架构下,如果任何一个worker down掉都不会影响整个系统的使用,
如果把client也与每个Job Server相连,那个任何一个Job Server down掉也不会影响整个系统的运行
Gearman提供有丰富的API支持,包括目前几乎所有的主流语言,当然也包括Ruby(gearman-ruby gem)
随gearmand发布的源码包中也附带了基于shell的client和worker命令行调用工具
Gearman需要依赖libevent和libevent的头文件, 因此在需要事先安装libevent的源码包,如果是redhat,debian或者ubuntu就需要安装libevent, libevent-devel(debian, ubuntu为libevent-dev)包,当然源码包还是最方便的,这里的采用的是Mac OS X 10.6,安装采用的是源码包
然后就可以直接编译安装gearmand了,这里采用的是gearmand-0.13.tar.gz
首先启动gearmand服务(job server)
#sbin/gearmand -u root -vv
或者后台运行-d,-vv打印日志启动
gearmand默认端口号为4730
shell下的调用
然后启动worker
#bin/gearman -w -f wc -- wc -l &
-w为指定worker, -f为方法名称, wc -l为方法内容
上面会启动一个worker进程
worker默认会连接localhost:4730端口,也可以自己指定多组Job Server,参数查看--help
client调用:
#bin/gearman -f wc < /etc/passwd
26
-f wc为制定调用的worker方法,/etc/passwd为参数
client默认也是连接localhost:4730,也可以自己指定多组Job Server,参数查看--help
通过以上shell的测试,Gearman的使用已经基本清晰了,下面结合Ruby我们来实战一下
首先安装Gearman的ruby API
#gem install gearman-ruby
worker.rb
require 'rubygems' require 'gearman' Gearman::Util.debug = true servers = ['localhost:4730'] w = Gearman::Worker.new(servers) w.add_ability('sum') do |args, job| num = args num.to_i * 100 end w.work
client.rb
require 'rubygems' require 'gearman' Gearman::Util.debug = true servers = ['localhost:4730'] client = Gearman::Client.new(servers) taskset = Gearman::Taskset.new task = Gearman::Task.new('sum', 2000) task.on_complete {|d| puts "TASK 1: #{d}" } taskset << task client.run(taskset)
测试
#ruby worker.rb
另一终端
#ruby client.rb
就可以看到结果了,也可以结合worker和job server的日志输出来观察
下面再来看一看怎样把gearman-ruby和Rails结合
在environment.rb中
require 'gearman' #需要首先启动gearmand, port: 4730 #然后启动worker Gearman::Util.debug = true GearmanClient = Gearman::Client.new(['localhost:4730', '192.168.1.109:4730']) module GearmanJob def self.do(call_name, args, task_hash_args = {}, &block) #taskset = Gearman::Taskset.new task_hash_args = { :background => false }.merge(task_hash_args) #gearman-ruby doesn't support asyc call now. task = Gearman::Task.new(call_name, args, task_hash_args) task.on_complete { |d| yield d } #if block_given? and !task_hash_args[:background] #task.on_status {|d| puts "Status: #{d}"} if task_hash_args[:background] #taskset << task GearmanClient.run(task) end end
在控制器中
def call GearmanJob.do(params[:call_name], params[:id]) do |data| render :inline => "output: #{data}" return end end
目前gearman-ruby还不支持异步调用,虽然可以使用:background => true参数,但是action还是会处于等待状态,只是不能得到worker的返回值,shitou和gearman-ruby的作者已经发邮件请教了这个问题,作者说会仔细研究下的,只有等待gearman-ruby作者的最新进展了
不过话说回来,如果真的需要后台运行任务的话可以直接使用starling, workling等工具,然后再结合gearman-ruby
参考资料
还有一个类似的工具Resque, 看这里
ttp://github.com/blog/542-introducing-resque
2010-06-05 11:26:41, 1182 reviews, comment
send to mailbox
少年,不点下广告吗!
all by shitou
blog comments powered by Disqus