PHP并发多进程处理利器Gearman使用介绍


Posted in PHP onMay 16, 2016

工作中我们有时候会遇到比如需要同时发布数据到多个个服务器上,或者同时处理多个任务。可以使用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 连接来进行的。

PHP并发多进程处理利器Gearman使用介绍

Gearman可以将工作的负载分担到不同的机器中。

PHP并发多进程处理利器Gearman使用介绍

安装:

rpm -ivh http://dl.iuscommunity.org/pub/ius/stable/Redhat/6/x86_64/epel-release-6-5.noarch.rpm

yum install -y gearmand

启动:
gearmand -d

安装PHP Gearman扩展
我都是用pcel来安装的,你也可以下载源码包来编译安装,但是记得要先安装libgearman和re2c,不然扩展编译安装会出错。

pecl install gearman #不成功并提示版本问题可以试试 pecl install gearman-1.0.3,默认好像是1.1.2
编译安装也很简单

wget -c http://pecl.php.net/get/gearman-1.1.1.tgz

tar zxvf gearman-1.1.1.tgz

phpize

./configure

make && make install

echo "extension=gearman.so" >> /etc/php.ini

PHP接口函数
Gearman提供很多完善的扩展函数,包括GearmanClient,GearmanJob,GearmanTask,GearmanWorker,具体可以查看PHP官方手册.
这是官方提供的Example其中的一个,相当与一个并发的分发任务处理的例子

<?php

$client = new GearmanClient();
$client->addServer();

// initialize the results of our 3 "query results" here
$userInfo = $friends = $posts = null;

// This sets up what gearman will callback to as tasks are returned to us.
// The $context helps us know which function is being returned so we can
// handle it correctly.
$client->setCompleteCallback(function(GearmanTask $task, $context) use (&$userInfo, &$friends, &$posts) {
switch ($context)
{
case 'lookup_user':
$userInfo = $task->data();
break;
case 'baconate':
$friends = $task->data();
break;
case 'get_latest_posts_by':
$posts = $task->data();
break;
}
});

// Here we queue up multiple tasks to be execute in *as much* parallelism as gearmand can give us
$client->addTask('lookup_user', 'joe@joe.com', 'lookup_user');
$client->addTask('baconate', 'joe@joe.com', 'baconate');
$client->addTask('get_latest_posts_by', 'joe@joe.com', 'get_latest_posts_by');

echo "Fetching...\n";
$start = microtime(true);
$client->runTasks();
$totaltime = number_format(microtime(true) - $start, 2);

echo "Got user info in: $totaltime seconds:\n";
var_dump($userInfo, $friends, $posts);

gearman_work.php

<?php

$worker = new GearmanWorker();
$worker->addServer();

$worker->addFunction('lookup_user', function(GearmanJob $job) {
// normally you'd so some very safe type checking and query binding to a database here.
// ...and we're gonna fake that.
sleep(3);
return 'The user requested (' . $job->workload() . ') is 7 feet tall and awesome';
});

$worker->addFunction('baconate', function(GearmanJob $job) {
sleep(3);
return 'The user (' . $job->workload() . ') is 1 degree away from Kevin Bacon';
});

$worker->addFunction('get_latest_posts_by', function(GearmanJob $job) {
sleep(3);
return 'The user (' . $job->workload() . ') has no posts, sorry!';
});

while ($worker->work());

我在3个终端中都执行了gearman_work.php

ryan@ryan-lamp:~$ ps aux | grep gearman* | grep -v grep
gearman 1504 0.0 0.1 60536 1264 ? Ssl 11:06 0:00 /usr/sbin/gearmand --pid-file=/var/run/gearman/gearmand.pid --user=gearman --daemon --log-file=/var/log/gearman-job-server/gearman.log --listen=127.0.0.1
ryan 2992 0.0 0.8 43340 9036 pts/0 S+ 14:05 0:00 php /var/www/gearmand_work.php
ryan 3713 0.0 0.8 43340 9036 pts/1 S+ 14:05 0:00 php /var/www/gearmand_work.php
ryan 3715 0.0 0.8 43340 9036 pts/2 S+ 14:05 0:00 php /var/www/gearmand_work.php

来查看下执行gearman_work.php的结果shell

Fetching...

Got user info in: 3.03 seconds:

string(59) "The user requested (joe@joe.com) is 7 feet tall and awesome"

string(56) "The user (joe@joe.com) is 1 degree away from Kevin Bacon"

string(43) "The user (joe@joe.com) has no posts, sorry!"

看到上面的3.03 seconds,说明client请求过去的任务被并行分发执行了。
在实际的生产环境中,为了监测gearmand和work的进程没有被意外退出,我们可以借助Supervisor这个工具.

PHP 相关文章推荐
基于mysql的论坛(2)
Oct 09 PHP
window+nginx+php环境配置 附配置搭配说明
Dec 29 PHP
php中常用字符串处理代码片段整理
Nov 07 PHP
PHP登陆后跳转到登陆前页面实现思路及代码
Jan 17 PHP
thinkPHP学习笔记之安装配置篇
Mar 05 PHP
PHP获得数组交集与差集的方法
Jun 10 PHP
PHP开发Apache服务器配置
Jul 15 PHP
PHP连接MYSQL数据库实例代码
Jan 20 PHP
PHP的邮件群发系统phplist配置方法详细总结
Mar 30 PHP
PHP yii实现model添加默认值的方法(两种方法)
Nov 10 PHP
ThinkPHP5框架实现简单的批量查询功能示例
Jun 07 PHP
PHP正则之正向预查与反向预查讲解与实例
Apr 06 PHP
php截取视频指定帧为图片
May 16 #PHP
PHP中常用的数组操作方法笔记整理
May 16 #PHP
PHP获取用户访问IP地址的5种方法
May 16 #PHP
php pdo oracle中文乱码的快速解决方法
May 16 #PHP
Yii2中OAuth扩展及QQ互联登录实现方法
May 16 #PHP
Yii2 assets清除缓存的方法
May 16 #PHP
php使用curl通过代理获取数据的实现方法
May 16 #PHP
You might like
功能齐全的PHP发送邮件类代码附详细说明
2008/07/10 PHP
php 删除cookie方法详解
2014/12/01 PHP
php自定义函数实现二维数组排序功能
2016/07/20 PHP
PHP实现通过二维数组键值获取一维键名操作示例
2019/10/11 PHP
用php实现分页效果的示例代码
2020/12/10 PHP
firefox中JS读取XML文件
2006/12/21 Javascript
Javascript 日期处理之时区问题
2009/10/08 Javascript
js apply/call/caller/callee/bind使用方法与区别分析
2009/10/28 Javascript
jQuery筛选器children()案例详解(图文)
2013/02/17 Javascript
利用JS判断用户是否上网(连接网络)
2013/12/23 Javascript
jQuery动画效果animate和scrollTop结合使用实例
2014/04/02 Javascript
JavaScript中Array的实用操作技巧分享
2016/09/11 Javascript
Vue 仿百度搜索功能实现代码
2017/02/16 Javascript
基于JS实现仿百度百家主页的轮播图效果
2017/03/06 Javascript
一篇文章让你彻底弄懂JS的事件冒泡和事件捕获
2017/08/14 Javascript
jquery点击回车键实现登录效果并默认焦点的方法
2018/03/09 jQuery
Node.Js生成比特币地址代码解析
2018/04/21 Javascript
JS实现随机抽选获奖者
2019/11/07 Javascript
Vue extend的基本用法(实例详解)
2019/12/09 Javascript
js键盘事件实现人物的行走
2020/01/17 Javascript
微信小程序实现分页加载效果
2020/11/19 Javascript
python实现比较两段文本不同之处的方法
2015/05/30 Python
Python3.6正式版新特性预览
2016/12/15 Python
Python实现的插入排序算法原理与用法实例分析
2017/11/22 Python
python切片及sys.argv[]用法详解
2018/05/25 Python
python3图片文件批量重命名处理
2019/10/31 Python
你可能不知道的Python 技巧小结
2020/01/29 Python
浅谈python多线程和多线程变量共享问题介绍
2020/04/17 Python
今天学到的CSS最新技术(与图片背景相关)
2012/12/24 HTML / CSS
大学生学期自我鉴定
2014/03/19 职场文书
大二学习计划书范文
2014/04/27 职场文书
企业承诺书怎么写
2014/05/24 职场文书
公司租车协议书
2015/01/29 职场文书
关于远足的感想
2015/08/10 职场文书
纪检干部学习心得体会
2016/01/23 职场文书
python中print格式化输出的问题
2021/04/16 Python