PS:对于在分布式网络环境中有大量计算任务的应用,如何有效的分布任务并且利用服务器的计算资源成为现代计算环境最大的挑战之一,Gearman程序框架可以让您轻松地将任务分布到网络中的其他机器节点。
Gearman介绍
Gearman是一个分发任务的程序框架,偏向于任务分发功能。对于分布式网络环境或者有大量任务的应用,Gearman提供了一个通用的应用程序框架将工作分包给更适合做这项任务的机器或者进程。它提供了你进行并行工作的能力、负载均衡处理的能力,以及在不同程序语言之间调用函数的能力。Gearman能够应用的领域非常广泛,从高可用的网站到数据库的复制任务。总之,Gearman就是负责分布式处理的中枢系统。
Gearman优点:
- 开源:Gearman免费并且开源而且有一个非常活跃的开源社区,licensing:BSD 。Gearman官网。Gearman文档官网
- 多语言支持:Gearman支持的语言种类非常丰富。我们能够用一种语言来编写Client程序,用另外一种语言编写Worker程序。Client:请求的发起者,可以是 C,PHP,Perl,MySQL UDF 等等。Worker:请求的处理者,可以是 C,PHP,Perl 等等。
- 灵活:不用指定任何特定的设计模式即可使用任何你选择的模型快速组建分布式应用程序,例如 Map/Reduce。
- 快速:Gearman的协议非常简单,优化了接口。C/C++写的服务,保证应用的负载在非常低的水平。
- 可植入:因为Gearman非常小巧、灵活。因此您可以将他置入到现有的任何系统中。
- 没有单点故障:Gearman可以在容错机制的帮助下规模化系统。
- 消息(message)大小没有限制——Gearman支持单4G大小的消息。
Gearman应用场景:
- 普通异步处理任务:订单处理,批量邮件,通知消息,群发短信,日志聚集
- 高CPU或内存的异步处理任务:MapReduce分布式并行运算,视频编码转码处理,后台图片裁剪处理
- 分布式和并行的处理任务:搜索,在线图片裁剪处理
- 定时处理:增量更新,数据复制
- 限制速率的FIFO处理:消息处理
- 分布式的系统监控任务
Gearman架构中的三个角色
- Client:请求的发起者,工作任务的需求方,用于向 job server 提交请求的客户机(可以是C、PHP、Java、Perl、Mysql udf等等)
- Job Server:请求的调度者,负责将client的请求转发给相应的worker(gearmand服务进程创建)
- Worker:请求(job,task)的处理者,注册到Job Server,接受Job Server分发的任务,实际执行任务,通过Job Server反馈结果给Client(可以是C、PHP、Java、Perl等等)
从上图可以看出,Gearman Client API,Gearman Worker API,Gearman Job Server都是由gearman本身提供,我们在应用中只需要调用即可。目前client与worker api都很丰富。
Gearman工作原理
Gearman的三个角色:Client -> Job Server -> Worker。
工作的流程如下图所示:
- Client的作用是提出一个 Job 任务交给 Job Server 任务服务器。
- Job Server 会去寻找一个合适的 Worker 来完成这项任务。
- Worker 执行由 Job Server 发送过来的Job,并且将结果通过 Job Server 返回给 Client。
Gearman 提供了 Client 和 Worker 的 API,利用这些API应用可以同 Gearman Job Server来进行通信。Gearman内部 Client 和 Worker 之间的通信都是通过 TCP协议 连接来进行的。
Client任务分类
Client有两种任务形式,分为job、Task:
/** * Tip: Task 与 Job区别 •Do和dobackground这类Do*函数下发的任务为job,每个任务只会在一个work上执行 •Task有组的概念,task是一组job,在下发后会并行执行并返回结果给调用方,Task内的子任务会下发给多个Work并行执行 */
任务按执行方式分:前台-同步阻塞(_JOB_HIGH,_JOB_LOW),后台-异步非阻塞(_JOB_HIGH_BG,_JOB_LOW_BG)
任务按优先级分:普通(SUBMIT_JOB),高优先级(SUBMIT_JOB_HIGH),低优先级(SUBMIT_JOB_LOW)
/** * Tip: 任务运行优先级 不管是job还是task,SUBMIT_JOB_HIGH > SUBMIT_JOB > SUBMIT_JOB_LOW 同等级的job或者task:在内存队列内,add时间早的(Task、job) > add时间晚的(Task、job) 同等级的task:在一组task内,add时间晚的(Task) > add时间早的(Task) */
前后台任务最大区别在于,”前台任务”发送job到job server后会一直等待work给它处理并返回结果,在此过程中,前台任务一直阻塞当前脚本往下执行,直到获取返回值!而”后台任务”仅仅是发送job到job server这个过程就结束了,所以client可以跟踪前台任务的工作状态,而不能跟踪BG(后台)任务
/*---------------------同步阻塞调用job----------------------*/ /** * (同步阻塞)正常优先级的job并等待返回结果 * Tip:在队列中等待时间过长有可能产生超时,超时设置timeout * @param string $function_name 由程序自动执行的已注册函数 * @param string $workload 被处理的序列化数据 * @param string $unique 用于标识特定job的唯一性ID。 * @return string 结果 */ public function doNormal($function_name,$workload,$unique=null) { return $this->gmclient->doNormal($function_name,$workload,$unique); } /** * (同步阻塞)高优先级的job并等待返回结果 * @param string $function_name 由程序自动执行的已注册函数 * @param string $workload 被处理的序列化数据 * @param string $unique 用于标识特定job的唯一性ID。 * @return string 结果 */ public function doHigh($function_name,$workload,$unique=null) { return $this->gmclient->doHigh($function_name,$workload,$unique); } /** * (同步阻塞)低优先级的job并等待返回结果 * @param string $function_name 由程序自动执行的已注册函数 * @param string $workload 被处理的序列化数据 * @param string $unique 用于标识特定job的唯一性ID。 * @return string 结果 */ public function doLow($function_name,$workload,$unique=null) { return $this->gmclient->doLow($function_name,$workload,$unique); }
/*---------------------异步非阻塞调用job----------------------*/ /** * (异步非阻塞)普通优先级job发送到job server并返回此job的句柄。 * @param string $function_name 由程序自动执行的已注册函数 * @param string $workload 被处理的序列化数据 * @param string $unique 用于标识特定job的唯一性ID。 * @return string 句柄 */ public function doBackground($function_name,$workload,$unique=null) { return $this->gmclient->doBackground($function_name,$workload,$unique); } /** * (异步非阻塞)高优先级job发送到job server并返回此job的句柄。 * @param string $function_name 由程序自动执行的已注册函数 * @param string $workload 被处理的序列化数据 * @param string $unique 用于标识特定job的唯一性ID。 * @return string 句柄 */ public function doHighBackground($function_name,$workload,$unique=null) { return $this->gmclient->doHighBackground($function_name,$workload,$unique); } /** * (异步非阻塞)低优先级job发送到job server并返回此job的句柄。 * @param string $function_name 由程序自动执行的已注册函数 * @param string $workload 被处理的序列化数据 * @param string $unique 用于标识特定job的唯一性ID。 * @return string 句柄 */ public function doLowBackground($function_name,$workload,$unique=null) { return $this->gmclient->doLowBackground($function_name,$workload,$unique); }
/*---------------------同步阻塞调用task----------------------/ * Tip: 同一个Task队列内任务: 不同优先级task运行顺序:addTaskHigh > addTask > addTaskLow 相同优先级task运行顺序:add时间晚的task > add时间早的task 不同Task队列任务所在的队列内: 同一时刻,队列内优先级task运行顺序:addTaskHigh > addTask > addTaskLow 同一时刻,相同优先级task运行顺序:add时间早的Task > add时间晚的Task /---------------------同步阻塞调用task----------------------*/ /** * (同步阻塞)正常优先级的task并等待返回结果 * Tip:在队列中等待时间过长有可能产生超时,超时设置timeout * @param string $function_name 由程序自动执行的已注册函数 * @param string $workload 被处理的序列化数据 * @param mix &$context 与任务关联的应用程序上下文 * @param string $unique 用于标识特定job的唯一性ID。 */ public function addTask($function_name,$workload,$context=null,$unique=null) { return $this->gmclient->addTask($function_name,$workload,$context,$unique); } /** * (同步阻塞)高优先级的task并等待返回结果 * @param string $function_name 由程序自动执行的已注册函数 * @param string $workload 被处理的序列化数据 * @param mix &$context 与任务关联的应用程序上下文 * @param string $unique 用于标识特定job的唯一性ID。 */ public function addTaskHigh($function_name,$workload,$context=null,$unique=null) { return $this->gmclient->addTaskHigh($function_name,$workload,$context,$unique); } /** * (同步阻塞)低优先级的task并等待返回结果 * @param string $function_name 由程序自动执行的已注册函数 * @param string $workload 被处理的序列化数据 * @param mix &$context 与任务关联的应用程序上下文 * @param string $unique 用于标识特定job的唯一性ID。 */ public function addTaskLow($function_name,$workload,$context=null,$unique=null) { return $this->gmclient->addTaskLow($function_name,$workload,$context,$unique); }
/*---------------------异步非阻塞调用task----------------------*/ /** * (异步非阻塞)普通优先级task发送到job server并返回此job的句柄。 * @param string $function_name 由程序自动执行的已注册函数 * @param string $workload 被处理的序列化数据 * @param mix &$context 与任务关联的应用程序上下文 * @param string $unique 用于标识特定job的唯一性ID。 */ public function addTaskBackground($function_name,$workload,$context=null,$unique=null) { return $this->gmclient->addTaskBackground($function_name,$workload,$context,$unique); } /** * (异步非阻塞)高优先级task发送到job server并返回此job的句柄。 * @param string $function_name 由程序自动执行的已注册函数 * @param string $workload 被处理的序列化数据 * @param mix &$context 与任务关联的应用程序上下文 * @param string $unique 用于标识特定job的唯一性ID。 */ public function addTaskHighBackground($function_name,$workload,$context=null,$unique=null) { return $this->gmclient->addTaskHighBackground ($function_name,$workload,$context,$unique); } /** * (异步非阻塞)低优先级task发送到job server并返回此job的句柄。 * @param string $function_name 由程序自动执行的已注册函数 * @param string $workload 被处理的序列化数据 * @param mix &$context 与任务关联的应用程序上下文 * @param string $unique 用于标识特定job的唯一性ID。 */ public function addTaskLowBackground($function_name,$workload,$context=null,$unique=null) { return $this->gmclient->addTaskLowBackground ($function_name,$workload,$context,$unique); }