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 相关文章推荐
PHPlet在Windows下的安装
Oct 09 PHP
php数组函数序列之sort() 对数组的元素值进行升序排序
Nov 02 PHP
解析PHP实现下载文件的两种方法
Jul 05 PHP
PHP动态生成javascript文件的2个例子
Apr 11 PHP
php中strstr、strrchr、substr、stristr四个函数的区别总结
Sep 22 PHP
php使用simplexml_load_file加载XML文件并显示XML的方法
Mar 19 PHP
PHP Curl模拟登录微信公众平台、新浪微博实例代码
Jan 28 PHP
PHP扩展迁移为PHP7扩展兼容性问题记录
Feb 15 PHP
php文件操作小结(删除指定文件/获取文件夹下的文件名/读取文件夹下图片名)
May 09 PHP
Laravel框架实现即点即改功能的方法分析
Oct 31 PHP
php中yii框架实例用法
Dec 22 PHP
PHP 对接美团大众点评团购券(门票)的开发步骤
Apr 03 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
Yii2 输出xml格式数据的方法
2016/05/03 PHP
PHP实现使用DOM将XML数据存入数组的方法示例
2017/09/27 PHP
ThinkPHP框架实现FTP图片上传功能示例
2019/04/08 PHP
基于PHP实现生成随机水印图片
2020/12/09 PHP
IE6中使用position导致页面变形的解决方案(js代码)
2011/01/09 Javascript
THREE.JS入门教程(4)创建粒子系统
2013/01/24 Javascript
jQuery Mobile的loading对话框显示/隐藏方法分享
2013/11/26 Javascript
将字符串中由空格隔开的每个单词首字母大写
2014/04/06 Javascript
JavaScript中对象属性的添加和删除示例
2014/05/12 Javascript
jquery实现当滑动到一定位置时固定效果
2014/06/17 Javascript
Bootstrap modal 多弹窗之叠加显示不出弹窗问题的解决方案
2017/02/23 Javascript
浅谈angularjs依赖服务注入写法的注意点
2017/04/24 Javascript
详解jenkins自动化部署vue
2019/05/14 Javascript
基于Express框架使用POST传递Form数据
2019/08/10 Javascript
jqGrid表格底部汇总、合计行footerrow处理
2019/08/21 Javascript
vue+webpack 更换主题N种方案优劣分析
2019/10/28 Javascript
python多重继承实例
2014/10/11 Python
零基础写python爬虫之使用urllib2组件抓取网页内容
2014/11/04 Python
Python中生成器和yield语句的用法详解
2015/04/17 Python
Python下的常用下载安装工具pip的安装方法
2015/11/13 Python
python 读取txt中每行数据,并且保存到excel中的实例
2018/04/29 Python
python按照多个条件排序的方法
2019/02/08 Python
python处理document文档保留原样式
2019/09/23 Python
python抓取多种类型的页面方法实例
2019/11/20 Python
3种python调用其他脚本的方法
2020/01/06 Python
cookies应对python反爬虫知识点详解
2020/11/25 Python
FC-Moto西班牙:摩托车手最大的购物场所之一
2019/04/11 全球购物
数据库测试通常都包括哪些方面
2015/11/30 面试题
大学生先进事迹材料
2014/02/16 职场文书
弘扬雷锋精神活动演讲稿
2014/03/04 职场文书
普通党员四风问题对照检查材料
2014/09/27 职场文书
2015年药品销售工作总结范文
2015/05/25 职场文书
大学生学生会工作总结2015
2015/05/26 职场文书
2015年生活老师工作总结
2015/05/27 职场文书
python使用pycharm安装pyqt5以及相关配置
2022/04/22 Python
pd.DataFrame中的几种索引变换的实现
2022/06/16 Python