PHP: Gearman实现分布式处理, 分布式任务分发框架Gearman教程

一. 场景分析

业务服务压力比较大,想把一些占用资源的功能异步到远程处理,比如记录业务日志,文件加密,文件分发到其他文件服务器节点上,检查文件服务器是否已同步,对用户上传的图片进行剪裁生成多份缩略图,视频转换,静态内容生成,清除缓存等等,这些请求耗时长,占用系统资源大,影响业务正常访问。这些问题会经常遇到的,如果这些任务都在用户请求过程中完成,服务器撑不撑得住暂不考虑,单凭用户体验角度考虑来说,那是难以忍受的。

二. 解决之道

对于这种需求,我们可以通过分布式计算,对任务进行拆分,转移到多台服务器上进行异步或同步处理。分布式消息队列有多种实现方式如rabbitmq、gearman等。 在这里主要说gearman—分布式处理系统。gearman由三部分组成:Job server,worker server,client server。 任务服务器job server运行这gearmand进程,来负责处理应用的远程调用请求,并且维护计算任务;工作服务器worker server负责向job server注册函数等待领取任务并执行实际的计算,然后将结果返回给job server;客户端client server提供gearman client API给应用程序调用,API支持多种语言如C、php、perl、python、mysql udf、java、ruby、go等等,主要是向job server添加任务,

流程图如下:

PHP: Gearman实现分布式处理, 分布式任务分发框架Gearman教程
PHP: Gearman实现分布式处理, 分布式任务分发框架Gearman教程

通常,多语言多系统之间的集成是个大问题,一般来说,人们多半会采用WebService的方式来处理此类集成问题,但不管采用何种风格的WebService,如RPC风格,或者REST风格,其本身都有一定的复杂性。相比之下,Gearman也能实现类似的作用,而且更简单易用。

一个Gearman请求的处理过程涉及三个角色:Client -> Job -> Worker。

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

因为Client,Worker并不限制用一样的语言,所以有利于多语言多系统之间的集成。

甚至我们通过增加更多的Worker,可以很方便的实现应用程序的分布式负载均衡架构。

客户端client server向gearman添加任务时,有三种模式:

1. 同步顺序处理 相当于消息队列,先进先出。
2. 同步并行处理 这种模式会阻塞后面的运行,将互不依赖的任务并行处理,大大缩短整体处理时间。
3. 异步后台处理 将耗时任务交给后台处理,不阻塞当前进程。

三. 应用实例

官网:http://gearman.org/download/

Job Server (gearmand) : https://github.com/gearman/gearmand/releases

Client & Worker APIs:https://launchpad.net/gearmand/

1.  安装Gearman server and library:

wget https://github.com/gearman/gearmand/releases/download/1.1.18/gearmand-1.1.18.tar.gz
tar zxf gearmand-1.1.18.tar.gz
cd gearmand-1.1.18
./configure
sudo make
sudo make install
中间可能会遇到些问题:
在./configure的时候,可能会出现缺少libraries的情况,一般是缺少libevent和uuid这两个开发包,安装之。。。

sudo apt-get install libevent-dev
sudo apt-get install uuid-dev

安装完成后再重新配置安装,安装完成后执行

sudo ldconfig

2. Gearman Client和Worker端PHP实现实例,安装Gearman PHP extension:

wget http://pecl.php.net/get/gearman-1.0.2.tgz
tar zxf gearman-1.0.2.tgz
cd gearman-1.0.2
phpize
./configure
sudo make
sudo make install

中间可能遇到的问题:找不到phpize命令,phpize在php开发包中,所以要先安装php7-dev

sudo apt-get install php7dev

安装完后,就可以在源码目录中执行phpize生成相关安装配置信息,接着执行后面的./configure等make install后,它告诉你一个目录,生成的gearman.so就在那里。根据需要考到相应PHP的扩展目录里(因为我直接用系统默认安装的php,它自动生成就在扩展中) 接下来修改php.ini以使php加载该模块:可以通过(可以通过 php –ini 命令快速找到这个文件)

php --ini

看下php.ini在哪里,sudo vim 修改之,在其中加入

extension = "gearman.so"

保存此文件。要想验证扩展是否启用,请运行 php –info,然后查找 Gearman

$ php --info | grep "gearman support"
gearman
gearman support => enabled
libgearman version => 1.1.18

此外,还可以用一个 PHP 代码片段来验证构建和安装是否得当。将这个小应用程序保存到 verify_gearman.php:

<?php
  print gearman_version() . "\n";
?>

接下来,从命令行运行此程序:

$ php verify_gearman.php
1.1.18

如果这个版本号与之前构建和安装的 Gearman 库的版本号相匹配,那么系统就已准备好了。

然后,开始编写client和worker端:

给出了用 PHP 编写的一个 producer,或 client。将此代码保存在一个名为 client.php 的文件内。
client.php

<?php
  $client= new GearmanClient();
  $client->addServer();
  print $client->do("title", "AlL THE World's a sTagE");
  print "\n";
?>

从 PHP 使用 Gearman 类似于之前的示例,惟一的区别在于这里是在 PHP 内创建 producer 和 consumer。每个 consumer 的工作均封装在一个或多个 PHP 函数内。

worker.php

<?php
  $worker= new GearmanWorker();
  $worker->addServer();
  $worker->addFunction("title", "title_function");
  while ($worker->work());
    
  function title_function($job)
  {
    return ucwords(strtolower($job->workload()));
  }
?>

现在,可以用如下的命令行连接客户机与 worker 了:
1、启动job

gearmand -d

2、启动worker

php -c /etc/php5/apache2/php.ini worker.php

3、启动client(新开终端中打开)

php -c /etc/php5/apache2/php.ini client.php

屏幕显示字符串的长度 “5” 这里,有几点需要说明一下:
1、这里直接用php cli方式运行,添加-c参数是为了加载php.ini配置文件,以加载gearman扩展
2、worker应该做成守护进程(CLI模式),可以开启多个,这样client发起的任务就会分发到各个worker分别来执行(自动负载均衡 ) 这个例子由于太过简单,即使开启多个worker也无法看出效果,不过可以通过终止其中一个,可以看出系统自动切换到其他worker继续正常执行
3、同理,client也是可以开启多个的(模型请参考之前的那边日志)
4、同时,job也可以开启多个,以避免单点故障

或者:

$ php worker.php &
$ php client.php
All The World's A Stage
$ jobs
[3]+  Running                 php worker.php &

Gearman 的高级特性

在一个 Web 应用程序内可能有许多地方都会用到 Gearman。可以导入大量数据、发送许多电子邮件、编码视频文件、挖据数据并构建一个中央日志设施 — 所有这些均不会影响站点的体验和响应性。可以并行地处理数据。而且,由于 Gearman 协议是独立于语言和平台的,所以您可以在解决方案中混合编程语言。比如,可以用 PHP 编写一个 producer,用 C、Ruby 或其他任何支持 Gearman 库的语言编写 worker。

一个连接客户机和 worker 的 Gearman 网络实际上可以使用任何您能想象得到的结构。很多配置能够运行多个代理并将 worker 分配到许多机器上。负载均衡是隐式的:每个可操作的可用 worker(可能是每个 worker 主机具有多个 worker)从队列中拉出作业。一个作业能够同步或异步运行并具有优先级。

Gearman 的最新版本已经将系统特性扩展到了包含持久的作业队列和用一个新协议来通过 HTTP 提交工作请求。对于前者,Gearman 工作队列保存在内存并在一个关系型数据库内存有备份。这样一来,如果 Gearman 守护程序故障,它就可以在重启后重新创建这个工作队列。另一个最新的改良通过一个 memcached 集群增加队列持久性。memcached 存储也依赖于内存,但被分散于几个机器以避免单点故障。

Gearman 是一个刚刚起步却很有实力的工作分发系统。据 Gearman 的作者 Eric Day 介绍,Yahoo! 在 60 或更多的服务器上使用 Gearman 每天处理 600 万个作业。新闻聚合器 Digg 也已构建了一个相同规模的 Gearman 网络,每天可处理 400,000 个作业。Gearman 的一个出色例子可以在 Narada 这个开源搜索引擎(参见 参考资料)中找到。

Gearman 的未来版本将收集并报告统计数据、提供高级监视和缓存作业结果等。为了跟踪这个 Gearman 项目,可以订阅它的 Google 组,或访问 Freenode 上它的 IRC 频道 #gearman

 

CHM手册: Gearman手册.zip

 

本文:PHP: Gearman实现分布式处理, 分布式任务分发框架Gearman教程