Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7894158
  • 博文数量: 701
  • 博客积分: 2150
  • 博客等级: 上尉
  • 技术积分: 13233
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-29 16:28
个人简介

天行健,君子以自强不息!

文章分类

全部博文(701)

文章存档

2019年(2)

2018年(12)

2017年(76)

2016年(120)

2015年(178)

2014年(129)

2013年(123)

2012年(61)

分类: 架构设计与优化

2016-06-15 20:11:59

一、Gearman介绍
gearman,从名字上看叫做“齿轮工”,就是通过齿轮把不同的组件组合在一起。
通常,多语言多系统之间的集成是项目开发中一个比较头疼的问题。
一般会采用RPC风格或者是REST风格的WebService。但是总感觉比较麻烦。
gearman就应运而生了,作为一个任务分发架构,
它能够轻松的将前端的任务通过Job Server分发给后端的Worker处理。

Gearman提供了一种通用的程序框架来将你的任务分发到不同的机器或者不同的进程当中。
它提供了你进行并行工作的能力、负载均衡处理的能力,以及在不同程序语言之间沟通的能力。
Gearman能够应用的领域非常广泛,从高可用的网站到数据库的复制任务。
总之,Gearman就是负责分发处理的中枢系统,它的优点包括:
 . 开源:Gearman免费并且开源而且有一个非常活跃的开源社区,如果你想来做一些贡献,请点击 。
 . 多语言支持:Gearman支持的语言种类非常丰富。
   让我们能够用一种语言来编写Worker程序,但是用另外一种语言编写Client程序。
 . 灵活:不必拘泥于固定的形式。您可以采用你希望的任何形式,例如 Map/Reduce。
 . 快速:Gearman的协议非常简单,并且有一个用C语言实现的,经过优化的服务器,
   保证应用的负载在非常低的水平。
 . 可植入:因为Gearman非常小巧、灵活。因此您可以将他置入到现有的任何系统中。
 . 没有单点:Gearman不仅可以帮助扩展系统,同样可以避免系统的失败。

二、Gearman的工作原理
使用Gearman的应用通常有三部分组成:
一个Client、一个Worker、一个任务服务器,即worker。 

Client:    请求的发起者,可以是C,PHP,Perl,MySQL UDF等等。
Job Server:请求的调度者,用来负责协调把Client发出的请求转发给合适的Worker。
Worker:    请求的处理者,可以是C,PHP,Perl等等。

Gearman请求的处理过程过程:
   Client -> Job Server -> Worker。

Client     的作用是提出一个 Job 任务交给 Job Server 任务服务器。
Job Server 会去寻找一个 合适的 Worker 来完成这项任务。
Worker     执行由 Client 发送过来的 Job,并且将结果通过 Job Server 返回给 Client。

Gearman 提供了 Client 和 Worker 的 API,利用这些API 应用可以同 Gearman Job Server来进行通信。
Gearman 内部 Client 和 Worker 之间的通信都是通过 TCP 连接来进行的。
工作的流程如下图所示:

Fig-1 

三、gearman的用处
Gearman首先提供了一个多语言通讯的接口,当然还有比这个更简单有效的办法。
Gearman可以将工作的负载分担到不同的机器中,如下图所示:

Fig-2

Job Server 可以开启多个实例,这样在其中一个发生故障的时候,可以 Failover 到其他的机器上。
同时 Worker 也可以是多个实例进行运行,因为当前的服务器很多都是多核的。

四、关于gearman的分布式任务处理:
1. 其实每一个任务处理的时间并没有降低,相反会稍稍有所增加,主要是数据在网络上传输的一些时间。
2. 前端Client(通常是web服务器)的负载降低了,但是转移到了后端Worker上。
   计算不可能凭空消失,只不过从一台机器转移到了另外一台机器。
3. 同步方式的话,前端Client(通常是Web服务器)等待的时间与后端Worker的数量与当前任务数有关。

如果任务数量<=Worker数量,前端Client等待的时间约等于一个任务处理的时间。
但是当任务数>=Worker数量时,就会出现某些Client等待的情况,
某个Client只有等到一个空闲的Worker,才会将任务交给它进行处理。

设想一下,在任务数<=Worker数量的时候,使用gearman是可以提高响应时间的。
现在有N个任务(Client),M个Worker,每个任务执行时间为t。
如果不是用gearman的话,需要的时间为N*t,平均等待时间为N*t/2。
如果使用了gearman的话,并且N<=M,需要的时间为t,平均等待时间为t;
如果N>M的话,需要的时间为(N/M)*t or (N/M+1)*t。

test.sh
#!/bin/sh
sleep 10
echo "TEST"

开启2个Worker
./gearman -w -f test /home/wangyao/test.sh

开启3个Client:
date;./gearman -f test;date
三个结果分别为:
--------------------------------------------
Wed Mar 17 14:41:31 CST 2010
TEST 
Wed Mar 17 14:41:41 CST 2010
--------------------------------------------
Wed Mar 17 14:41:32 CST 2010
TEST 
Wed Mar 17 14:41:42 CST 2010
--------------------------------------------
Wed Mar 17 14:41:34 CST 2010
TEST 
Wed Mar 17 14:41:51 CST 2010
--------------------------------------------
可以看出前两个Client的任务都用了10s,但是第3个任务却花了17s。
主要在于当第3个任务执行的时候,没有空闲的Worker执行任务,必须等到一个Worker空闲下来,
最先空闲的Worker要在14:41:41,在这个时刻执行第3个任务,现在已经过去了7s,再需要10s完成任务,
因此第3个任务最终用了17s。

4. 异步方式的话,
任务交给后端Worker后,前端Client就返回了,这样用户体验比较好。
但是,存在任务执行失败或者是任务结果反馈的问题。
一般采用数据库作为存储,将任务执行的状态信息、结果等存入数据库;
前端Client定期检查数据库中的结果,再进一步进行操作,是向用户呈现结果还是重新执行任务。

一个应用实例:
Client将log发送到专门的log服务器:
tail -f access_log | gearman -h host -f logger

可能会有多个log服务器,log服务器将接受到的log信息写入到一个文件中:
gearman -w -h host -f logger > log_file

进行分布式grep,需要在每台log服务器设置一个function:
gearman -w host -f logger1 ./dgrep.sh

#!/bin/sh
read pattern
grep $pattern log_file


相应的在其他log服务器上创建logger2,logger3等。

现在,日志已经在日志服务器上了。
我们在其他机器上,想对日志进行分布式的grep。
只需要作为一个client,调用worker logger1、logger2、logger3等。
gearman -h host -f logger1 -f logger2 -f logger3 KEYWORD 
这就可以可以在所有的机器上grep KEYWORD了。

这种方法不是很灵活,每台机器设置一个func,对上层不透明。

总体来看,gearman适合于那种task数量远远大于worker数量的应用。
理论上来看,将计算开销转移到Worker上,从而实现任务的并发执行,
表现为client计算负载减轻,用户的等待时间减少。
对Client而言是task,对于Worker而言是job。

后记:
gearman的源码还是值得阅读的,对于设计高并发网络程序有些帮助,
其中的架构跟我现在项目中用的差不多,但是有一点感觉不错,
只有一个维护对应表的逻辑线程,并且尽量减少系统调用。
gearman的消息传递模式是一对一的,不能实现一对多,
一个client通过job server最后只能够到达一个worker上。
如果需要一对多,需要定义多个worker的function,依次向这些worker进行发送,非常的不方便。
这一点就不如ZeroMQ,ZeroMQ支持的模式很多,能够满足各种消息队列需求。

参考:


http://blog.s135.com/dips/


阅读(1741) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~