Gearman——分布式任务分发框架
工作中我们有时候会遇到比如需要同时发布数据到多个个服务器上,或者同时处理多个任务。可以使用PHP的curl_multi的方式并发处理请求,但是由于网络和数据以及各个服务器等等的一些情况导致这种并发处理的响应时间很慢,因为在并发请求的过程中还包括记录日志,处理数据等逻辑,等待处理结果并返回,所以也不能友好的满足后台操作的体验。 现在有另外一种方案,利Gearman来实现并发的需求。通过Client将请求发送到Gearman的Jobs,在每个Work中来再来进行curl_multi和数据处理和日志等一些操作,同时用supervisor 来监控Gearman以及Works的进程,这样可以实现一个并行的多进程和负载均衡的方案。 Gearman可以做什么: 异步处理:图片处理,订单处理,批量邮件/通知之类的 要求高CPU或内存的处理:大容量的数据处理,MapReduce运算,日志聚集,视频编码 分布式和并行的处理 定时处理:增量更新,数据复制 限制速率的FIFO处理 分布式的系统监控任务 Gearman工作原理: 使用Gearman的应用通常有三部分组成:一个Client、一个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 连接来进行的。 通常,多语言多系统之间的集成是个大问题,一般来说,人们多半会采用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,可以很方便的实现应用程序的分布式负载均衡架构。 3 Gearman下载 1)官网 http://gearman.org/ 2)官网下载 https://launchpad.net/gearmand 3)官网使用向导 http://gearman.org/getting-started/ 3)本次安装用到的所有软件下载地址(安装环境为CentOS-6.5) http://download.csdn.net/detail/clevercode/8698699 4 Gearman安装 4.1 安装linux必备常用库 Linux中必备常用支持库的安装:http://blog.csdn.net/clevercode/article/details/45438401 4.2 安装gearmand依赖的库 # yum install -y boost-devel gperf libevent-devel libuuid-devel 4.3 安装gearmand服务 1)解压 # cd /usr/local/src/gearman # tar xzf gearmand-1.1.12.tar.gz 2)配置 # cd gearmand-1.1.12 # ./configure 3)编译 # make 4)安装 # make install 5)安装成功图,输入 # gearman 5 安装php扩展 1)安装phpize # yum install -y php-devel 2)解压 # cd /usr/local/src/gearman # tar xzf gearman-1.1.2.tgz 3)配置 # cd gearman-1.1.2 # phpize # ./configure 4)编译 # make 5)安装 # make install 6)安装成功 出现“Installing shared extensions: /usr/lib64/PHP/modules/”表示安装成功,/usr/lib64/php/modules/是gearman.so扩展的目录。如图 7)配置(加入扩展) # vi /usr/local/php5/etc/php.ini extension="gearman.so" 8)查配置是否成功 # vi test.php print gearman_version() . "\n"; ?> 执行php test.php后,出现1.1.12表示安装成功 # php test.php 1.1.12 6 Gearman启动停止 1) 创建日志/data0/logs/gearmand.log # touch /data0/logs/gearmand.log 2)启动 # /usr/local/sbin/gearmand -d -u root -L 192.168.142.130 --log-file=/data0/logs/gearmand.log 3)参数详解 -b,--backlog= 储备的监听连接数量 -d, --daemon 后台运行 -f, --file-descriptors= 文件描述符的数量 -h, --help 帮助 -j, --job-retries= 在ob server移除不可用job之前运行的次数,防止不断运行导致其他可用worker崩溃。默认没有限制 -l, -log-file= 日志文件存放位置(默认记录最简单日志) -L, --listen= 监听的IP,默认全部接受 -p, --port= 指定监听端口 -P, --pid-file= 指定进程ID写入位置 -r, --protocol= 加载协议模块 -q, --queue-type= 指定持久化队列 -t, --threads= 使用的I/9线程数量。默认为0 -u, --user= 启动后,切换到指定用户 -v, --verbose 增加一级详细程度 -V, --version 显示版本信息 4)查是否运行 # ps axu | grep gearmand 5)查看监听端口 # netstat -anp | grep 4730 6)停止,直接kill掉进程。 7 Gearman使用 7.1 创建Worker 创建worker.php,创建一个发送邮件的Worker端。代码如下 [php]view plaincopy $worker=newGearmanWorker(); $worker->addServer('192.168.142.130','4730'); $worker->addFunction("sendMail","my_sendmail_function"); while($worker->work()); functionmy_sendmail_function($job){ //接收数据 $tmp=$job->workload(); $receiveArr=unserialize($tmp); $from=$receiveArr['from']; $to=$receiveArr['to']; $subject=$receiveArr['subject']; $content=$receiveArr['content']; //发送邮件 //.... return$subject.'sendmailOK'; } ?> 7.2 启动Worker端 如果处理的数据量大,可以执行以下脚本多次,即启动多个Worker端。 # nohup php worker.php > tmp.txt & 7.3 创建Client(阻塞模式,需要等待返回结果才结束) 创建一个client.php。do()方法是阻塞模式,必须等待worker端返回结果,程序才能停止。(如图返回:hello Gearman sendmail OK) [php]view plaincopy $client=newGearmanClient(); $client->addServer('192.168.142.130','4730'); $job=array(); $job['from']='Code'; $job['to']='Gearman'; $job['subject']='helloGearman'; $job['content']='helloGearman:thisisfromGearmanClient'; $job=serialize($job); //等到worker端返回结果,才会结束。 $ret=$client->do("sendMail",$job); echo$ret."\r\n"; ?> 7.4 创建Client(非阻塞,不用等结果) 创建一个client2.php。doBackground()不用等待worker端返回结果,程序就结束了。 [php]view plaincopy $client=newGearmanClient(); $client->addServer('192.168.142.130','4730'); $job=array(); $job['from']='Code'; $job['to']='Gearman'; $job['subject']='helloGearman'; $job['content']='helloGearman:thisisfromGearmanClient'; $job=serialize($job); //不等待返回结果,就会结束 $ret=$client->doBackground("sendMail",$job); echo$ret."\r\n"; ?> 8 Gearman管理 输入以下命令,查看4730端口情况。 # (echo "status" ; sleep 2 ) | telnet 192.168.142.130 4730 1)字段说明:"已知注册的任务" "正在运行的任务" "队列中的任务" "可用的 Worker". 2)sendMail 0 0 1,注册的任务名为 sendMail,0 个正常在运行,队列为空,有一个可用的 Worker.