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 相关文章推荐
PHP 引用是个坏习惯
Mar 12 PHP
php快速url重写 更新版[需php 5.30以上]
Apr 20 PHP
php下正则来匹配dede模板标签的代码
Aug 21 PHP
PHP安全防范技巧分享
Nov 03 PHP
深入掌握include_once与require_once的区别
Jun 17 PHP
基于php中使用excel的简单介绍
Aug 02 PHP
php全角字符转换为半角函数
Feb 07 PHP
windows7下安装php的imagick和imagemagick扩展教程
Jul 04 PHP
php阿拉伯数字转中文人民币大写
Dec 21 PHP
Yii 2.0中场景的使用教程
Jun 02 PHP
php解决约瑟夫环算法实例分析
Sep 30 PHP
Laravel实现批量更新多条数据
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使用qr生成二维码的示例分享
2014/01/20 PHP
PHP基于新浪IP库获取IP详细地址的方法
2017/05/04 PHP
用js实现的检测浏览器和系统的函数
2009/04/09 Javascript
基于jquery的划词搜索实现(备忘)
2010/09/14 Javascript
利用js动态添加删除table行的示例代码
2013/12/16 Javascript
浅析JavaScript事件和方法
2015/02/28 Javascript
js实现浏览本地文件并显示扩展名的方法
2015/08/17 Javascript
jQuery插件ImageDrawer.js实现动态绘制图片动画(附源码下载)
2016/02/25 Javascript
内容滑动切换效果jquery.hwSlide.js插件封装
2016/07/07 Javascript
Ionic2调用本地SQlite实例
2017/04/22 Javascript
vue调用高德地图实例代码
2017/04/28 Javascript
Angular2学习教程之组件中的DOM操作详解
2017/05/28 Javascript
微信小程序日历组件calendar详解及实例
2017/06/08 Javascript
浅谈vue引入css,less遇到的坑和解决方法
2018/01/20 Javascript
基于webpack4搭建的react项目框架的方法
2018/06/30 Javascript
jQuery实现table表格checkbox全选的方法分析
2018/07/04 jQuery
vue利用全局导航守卫作登录后跳转到未登录前指定页面的实例代码
2020/05/19 Javascript
vue实现移动端返回顶部
2020/10/12 Javascript
详解在Python中处理异常的教程
2015/05/24 Python
Python 编程速成(推荐)
2019/04/15 Python
python实现websocket的客户端压力测试
2019/06/25 Python
Python列表list操作相关知识小结
2020/01/29 Python
英国翻新电子产品购物网站:Tech Trade
2017/12/25 全球购物
Under Armour安德玛中国官网:美国高端运动科技品牌
2018/03/09 全球购物
重新定义牛仔布,100美元以下:Warp + Weft
2018/07/25 全球购物
物业门卫岗位职责
2013/12/28 职场文书
中学生演讲稿
2014/04/26 职场文书
关于环保的活动方案
2014/08/25 职场文书
群众路线教育实践活动个人对照检查材料
2014/09/22 职场文书
机票销售员态度不好检讨书
2014/09/27 职场文书
作风整顿个人剖析材料
2014/10/06 职场文书
复兴之路纪录片观后感
2015/06/02 职场文书
银行培训心得体会范文
2016/01/09 职场文书
学校中层领导培训心得体会
2016/01/11 职场文书
解决numpy数组互换两行及赋值的问题
2021/04/17 Python
python 办公自动化——基于pyqt5和openpyxl统计符合要求的名单
2021/05/25 Python