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 相关文章推荐
windows xp下安装pear
Dec 02 PHP
php下用GD生成生成缩略图的两个选择和区别
Apr 17 PHP
php中XMLHttpRequest(Ajax)不能设置自定义的Referer的解决方法
Nov 26 PHP
php实现mysql数据库操作类分享
Feb 14 PHP
php socket客户端及服务器端应用实例
Jul 04 PHP
PHP制作图形验证码代码分享
Oct 23 PHP
php列出mysql表所有行和列的方法
Mar 13 PHP
PHP中的类型提示(type hinting)功能介绍
Jul 01 PHP
学习php设计模式 php实现访问者模式(Visitor)
Dec 07 PHP
php实现将二维关联数组转换成字符串的方法详解
Jul 31 PHP
PHP+Session防止表单重复提交的解决方法
Apr 09 PHP
Linux下安装Memcached服务器和客户端与PHP使用示例
Apr 15 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简单解析mysqli查询结果的方法(2种方法)
2016/06/29 PHP
thinkphp3.2实现在线留言提交验证码功能
2017/07/19 PHP
FormValid0.5版本发布,带ajax自定义验证例子
2007/08/17 Javascript
JavaScript 以对象为索引的关联数组
2010/05/19 Javascript
用jquery统计子菜单的条数示例代码
2013/10/18 Javascript
仿百度联盟对联广告实现代码
2014/08/30 Javascript
jQuery滚动条插件nanoscroller使用指南
2015/04/21 Javascript
微信开发 消息推送实现代码
2016/10/21 Javascript
Vue 实用分页paging实例代码
2017/04/12 Javascript
js自定义trim函数实现删除两端空格功能
2018/02/09 Javascript
vue2.0+vuex+localStorage代办事项应用实现详解
2018/05/31 Javascript
ES6 如何改变JS内置行为的代理与反射
2019/02/11 Javascript
[01:32]2016国际邀请赛中国区预选赛CDEC战队教练采访
2016/06/26 DOTA
python去除所有html标签的方法
2015/05/05 Python
在python3.5中使用OpenCV的实例讲解
2018/04/02 Python
使用PM2+nginx部署python项目的方法示例
2018/11/07 Python
Python实用工具FuckIt.py介绍
2019/07/02 Python
Python3 requests文件下载 期间显示文件信息和下载进度代码实例
2019/08/16 Python
Python实现PS滤镜中的USM锐化效果
2020/12/04 Python
CSS3的颜色渐变效果的示例代码
2017/09/29 HTML / CSS
HTML5表单验证特性(知识点小结)
2020/03/10 HTML / CSS
美国职棒大联盟官方网上商店:MLBShop.com
2017/11/12 全球购物
迪奥美国官网:Dior美国
2019/12/07 全球购物
Can a struct inherit from another class? (结构体能继承类吗)
2014/07/22 面试题
财务部岗位职责
2013/11/19 职场文书
生产车间班组长岗位职责
2014/01/06 职场文书
商场端午节活动方案
2014/01/29 职场文书
办公室文员工作职责
2014/01/31 职场文书
刑事辩护授权委托书范本
2014/10/17 职场文书
世界卫生日宣传活动总结
2015/02/09 职场文书
2019年行政人事个人工作总结范本!
2019/07/19 职场文书
MySQL表的增删改查(基础)
2021/04/05 MySQL
Python进度条的使用
2021/05/17 Python
Vue + iView实现Excel上传功能的完整代码
2021/06/22 Vue.js
windows安装 redis 6.2.6最新步骤详解
2022/04/26 Redis
Windows server 2016服务器基本设置
2022/08/14 Servers