From : http://www.yuansir-web.com/2013/11/25/php%E5%88%A9%E7%94%A8gearman%E6%9D%A5%E5%A4%84%E7%90%86%E5%B9%B6%E8%A1%8C%E5%A4%9A%E8%BF%9B%E7%A8%8B%E9%97%AE%E9%A2%98/
最近工作中开发的一套系统,其中很多都是需要操作多服务器的,比如需要同时发布数据到2000个服务器上,或者同时向2000个服务器拉取数据。刚开始的解决方案就是单纯用PHP的curl_multi的方式并发处理请求,而且参考了淘宝技术博客的《Rolling cURL: PHP并发最佳实践》,但是由于网络和数据以及各个服务器等等的一些情况导致这种并发处理的响应时间很慢,因为在并发请求的过程中还包括记录日志,处理数据等逻辑,等待处理结果并返回,所以也不能友好的满足后台操作的体验。
现在重新设计一种方案,利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 连接来进行的。
Gearman可以将工作的负载分担到不同的机器中。
安装配置
我只是记录下我安装配置的过程,我在Ubuntu和CentOS中都试了下。
CentOS YUM 安装
2 |
yum install -y gearmand |
Ubuntu apt 安装
1 |
apt-get install gearman |
源码编译
1 |
yum install uuid-devel libuuid libuuid-devel uuid boost-devel libevent libevent-devel |
3 |
tar zxvf gearmand-1.1.7. tar .gz |
4 |
./configure --prefix=/usr/ local /gearmand |
安装好以后启动
加上-d参数是表示后台运行,你可以gearmand -h 来查看其它的选项,启动的时候带上其它配置参数
1 |
/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 |
安装PHP Gearman扩展
我都是用pcel来安装的,你也可以下载源码包来编译安装,但是记得要先安装libgearman和re2c,不然扩展编译安装会出错。
01 |
pecl install gearman #不成功并提示版本问题可以试试 pecl install gearman-1.0.3,默认好像是1.1.2 |
06 |
tar zxvf gearman-1.1.1.tgz |
10 |
echo "extension=gearman.so" >> /etc/php.ini |
PHP接口函数
Gearman提供很多完善的扩展函数,包括GearmanClient,GearmanJob,GearmanTask,GearmanWorker,具体可以查看PHP官方手册.
这是官方提供的Example其中的一个,相当与一个并发的分发任务处理的例子
gearman_client.php
03 |
$client = new GearmanClient(); |
06 |
// initialize the results of our 3 "query results" here |
07 |
$userInfo = $friends = $posts = null; |
09 |
// This sets up what gearman will callback to as tasks are returned to us. |
10 |
// The $context helps us know which function is being returned so we can |
11 |
// handle it correctly. |
12 |
$client ->setCompleteCallback( function (GearmanTask $task , $context ) use (& $userInfo , & $friends , & $posts ) { |
16 |
$userInfo = $task ->data(); |
19 |
$friends = $task ->data(); |
21 |
case 'get_latest_posts_by' : |
22 |
$posts = $task ->data(); |
27 |
// Here we queue up multiple tasks to be execute in *as much* parallelism as gearmand can give us |
28 |
$client ->addTask( 'lookup_user' , 'joe@joe.com' , 'lookup_user' ); |
29 |
$client ->addTask( 'baconate' , 'joe@joe.com' , 'baconate' ); |
30 |
$client ->addTask( 'get_latest_posts_by' , 'joe@joe.com' , 'get_latest_posts_by' ); |
33 |
$start = microtime(true); |
35 |
$totaltime = number_format(microtime(true) - $start , 2); |
37 |
echo "Got user info in: $totaltime seconds:\n" ; |
38 |
var_dump( $userInfo , $friends , $posts ); |
gearman_work.php
03 |
$worker = new GearmanWorker(); |
06 |
$worker ->addFunction( 'lookup_user' , function (GearmanJob $job ) { |
07 |
// normally you'd so some very safe type checking and query binding to a database here. |
08 |
// ...and we're gonna fake that. |
10 |
return 'The user requested (' . $job ->workload() . ') is 7 feet tall and awesome' ; |
13 |
$worker ->addFunction( 'baconate' , function (GearmanJob $job ) { |
15 |
return 'The user (' . $job ->workload() . ') is 1 degree away from Kevin Bacon' ; |
18 |
$worker ->addFunction( 'get_latest_posts_by' , function (GearmanJob $job ) { |
20 |
return 'The user (' . $job ->workload() . ') has no posts, sorry!' ; |
23 |
while ( $worker ->work()); |
我在3个终端中都执行了gearman_work.php
1 |
ryan@ryan-lamp:~$ ps aux | grep gearman* | grep - v grep |
2 |
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 |
3 |
ryan 2992 0.0 0.8 43340 9036 pts/0 S+ 14:05 0:00 php /var/www/gearmand_work.php |
4 |
ryan 3713 0.0 0.8 43340 9036 pts/1 S+ 14:05 0:00 php /var/www/gearmand_work.php |
5 |
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
2 |
Got user info in : 3.03 seconds: |
3 |
string(59) "The user requested (joe@joe.com) is 7 feet tall and awesome" |
4 |
string(56) "The user (joe@joe.com) is 1 degree away from Kevin Bacon" |
5 |
string(43) "The user (joe@joe.com) has no posts, sorry!" |
看到上面的3.03 seconds,说明client请求过去的任务被并行分发执行了。
在实际的生产环境中,为了监测gearmand和work的进程没有被意外退出,我们可以借助Supervisor这个工具,下次我再单独来写个Supervisor的笔记。
- 利用Gearman实现并发查询(Multi-Query)
这个样例是想从数据库查询出几个结果集,一般的做法是,一个接一个的发送查询,然后汇总结果进行输出. 以下我们利用Gearman的gearman_client_run_tasks实现并发的查询,gearm ...
- Android平台利用OpenCL框架实现并行开发初试
http://www.cnblogs.com/lifan3a/articles/4607659.html 在我们熟知的桌面平台,GPU得到了极为广泛的应用,小到各种电子游戏,大到高性能计算,多核心.高 ...
- .Net Core中利用TPL(任务并行库)构建Pipeline处理Dataflow
在学习的过程中,看一些一线的技术文档很吃力,而且考虑到国内那些技术牛人英语都不差的,要向他们看齐,所以每天下班都在疯狂地背单词,博客有些日子没有更新了,见谅见谅 什么是TPL? Task Parall ...
- 利用gearman同步mysql数据到redis
一.Gearman 1.Gearman是一个分发任务的程序框架. 2.体系:a.client:发送一个jobb.server:找到合适的worker,把job交给该workerc.worker:处理j ...
- 利用 Gearman 实现系统错误报警功能
Gearman 是什么? Gearman是一个用来把工作委派给其他机器.分布式的调用更适合做某项工作的机器.并发的做某项工作在多个调用间做负载均衡.或用来在调用其它语言的函数的系统. Gearman ...
- 利用TPL(任务并行库)构建Pipeline处理Dataflow
https://www.cnblogs.com/CoderAyu/p/9757389.html
- gearman安装及初次使用
官网: http://gearman.org/ 一篇文章: 利用Gearman实现异步任务处理 一.问题分析 问题:在性能测试过程中,发现用户管理平台在进行图片上传时,性能不佳. 分析:经过代码分析 ...
- go/node/python 多进程与多核cpu
node node单线程,没有并发,但是可以利用cluster进行多cpu的利用.cluster是基于child_process的封装,帮你做了创建子进程,负载均衡,IPC的封装. const clu ...
- C++并行编程1
what is concurrency 我们可以一边看电视,一边唱歌.人并行非常容易理解,但是计算机呢?是不是我们一边编辑着word文档,一边听着歌,这样计算机就是在并行吗?不一定欧,如果你计算机是单 ...
随机推荐
- selenium自动测试
import requestsimport sysimport iofrom selenium import webdriverfrom selenium.webdriver.common.actio ...
- Web开发模式演变(转)
add by zhj:目前用的最多应该是模式二,其次是三.四,而模式五比较新,我自己也不太懂. 模式二--前后台交互的方式为整个页面,即每次请求,服务器都将HTML模板渲染后发给客户端,每次请求都返回 ...
- css样式大全整理
字体属性:(font) 大小 {font-size: x-large;}(特大) xx-small;(极小) 一般中文用不到,只要用数值就可以,单位:PX.PD 样式 {font-style: obl ...
- 统计Mongo数组中相同对象的属性之和
统计Mongo数组中相同对象的属性之和 需求 需要统计app端用户的行为,按天分表,存入mongo.每次用户进行操作的时候,将数据存入app本地,下次用户启动的时候,提交存入mongo,删除app本地 ...
- Mac 下的 .app文件如何生成.dmg ?
安装 Node.js最新版. 安装方法不赘述. 安装 create-dmg: sudo npm install --global create-dmg 注意这里 sudo不能少. 终端切换到 .app ...
- android listView 点两下才监听到
因为 对应的控件设置了 android:focusableInTouchMode="true" 意思是 触摸模式下 点击第一次 是 获得焦点.===
- GEEK-2018之隐藏在混乱之中的绝密情报 writeup
题目如上 打开题目后发现,提示robots 随后提示又需要改一改名字 修改文件名为humans.txt之后发现 有个备份文件,直接访问www.zip就可以下载了 下载打开后如下: 在其中看到了unse ...
- 在Activity中响应ListView内部按钮的点击事件的两种方法
转载:http://www.cnblogs.com/ivan-xu/p/4124967.html 最近交流群里面有人问到一个问题:如何在Activity中响应ListView内部按钮的点击事件,不要在 ...
- BZOJ 4610: [Wf2016]Ceiling Functi 水题
4610: [Wf2016]Ceiling Functi 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4610 Description ...
- html5 js实现浏览器全屏
全屏 var docElm = document.documentElement; //W3C if (docElm.requestFullscreen) { docElm.requestFullsc ...