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 相关文章推荐
简单易用的计数器(数据库)
Oct 09 PHP
PHP 将图片按创建时间进行分类存储的实现代码
Jan 05 PHP
PHP 动态生成静态HTML页面示例代码
Jan 15 PHP
ThinkPHP模板判断输出Empty标签用法详解
Jun 30 PHP
PHP下载远程文件到本地存储的方法
Mar 24 PHP
php获取json数据所有的节点路径
May 17 PHP
php实现通过ftp上传文件
Jun 19 PHP
初识通用数据库操作类――前端easyui-datagrid,form(php)
Jul 31 PHP
php防止用户重复提交表单
Nov 02 PHP
教你php如何实现验证码
Jan 20 PHP
PHP获取远程http或ftp文件的md5值的方法
Apr 15 PHP
ThinkPHP5与单元测试PHPUnit使用详解
Feb 23 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
DC这些乐高系列动画电影你看过几部?
2020/04/09 欧美动漫
php判断表是否存在的方法
2015/06/18 PHP
PHP安装GeoIP扩展根据IP获取地理位置及计算距离的方法
2016/07/01 PHP
PHP设计模式之原型设计模式原理与用法分析
2018/04/25 PHP
IE和Firefox在JavaScript应用中的兼容性探讨
2008/04/01 Javascript
jquery tablesorter.js 支持中文表格排序改进
2009/12/09 Javascript
js跨域问题之跨域iframe自适应大小实现代码
2010/07/17 Javascript
javascript使用window.open提示“已经计划系统关机”的原因
2014/08/15 Javascript
Jquery实现仿腾讯微博发表广播
2014/11/17 Javascript
Windows系统下使用Sublime搭建nodejs环境
2015/04/13 NodeJs
javascript判断并获取注册表中可信任站点的方法
2015/06/01 Javascript
ECMA5数组的新增方法有哪些及forEach()模仿实现
2015/11/03 Javascript
Jquery跨域获得Json的简单实例
2016/05/18 Javascript
js初始化验证实例详解
2016/11/26 Javascript
Vue.js第四天学习笔记(组件)
2016/12/02 Javascript
一道面试题引发的对javascript类型转换的思考
2017/03/06 Javascript
浅谈vuex之mutation和action的基本使用
2017/08/29 Javascript
JavaScript原型对象、构造函数和实例对象功能与用法详解
2018/08/04 Javascript
vue如何使用外部特殊字体的操作
2020/07/30 Javascript
Vue组件通信$attrs、$listeners实现原理解析
2020/09/03 Javascript
vue项目配置同一局域网可使用ip访问的操作
2020/10/23 Javascript
jQuery实现鼠标拖动图片功能
2021/03/04 jQuery
vue 数据双向绑定的实现方法
2021/03/04 Vue.js
Anaconda 离线安装 python 包的操作方法
2018/06/11 Python
详解python websocket获取实时数据的几种常见链接方式
2019/07/01 Python
快速解释如何使用pandas的inplace参数的使用
2020/07/23 Python
详解Python调用系统命令的六种方法
2021/01/28 Python
css3如何绘制一个圆圆的loading转圈动画
2018/01/09 HTML / CSS
使用Html5中的cavas画一面国旗
2019/09/25 HTML / CSS
举例说明类变量和实例变量的区别
2016/06/30 面试题
企业法人代表任命书
2014/06/06 职场文书
环境日宣传活动总结
2014/07/09 职场文书
2014党的群众路线教育实践活动总结报告
2014/10/31 职场文书
2015年母亲节活动总结
2015/02/10 职场文书
2015年数学教研工作总结
2015/07/22 职场文书
Python还能这么玩之用Python做个小游戏的外挂
2021/06/04 Python