官网: http://gearman.org/php
一篇文章:html
利用Gearman实现异步任务处理node
1、问题分析git
问题:在性能测试过程当中,发现用户管理平台在进行图片上传时,性能不佳。github
分析:通过代码分析得知,主要的瓶颈是图片上传后,还须要根据图片组件所在页面模块容器进行一系列处理:图片生成缩略图,裁剪图片,加水印等,这些处理在高并发的状况下,会消耗大量cpu资源,致使系统响应速度很是慢。sql
旧的处理方式:数据库
次控端调用前台接口进行上传图片后,前台程序先上传图片,接着,进行图片压缩等处理,而后再返回结果给次控端。编程
整个过程是串行的,次控端须要等待前台的结果后,再显示给用户。这个过程存在时间浪费,图片的处理能够提交到后台再进行处理,不须要立刻处理。ubuntu
所以,考虑采用Gearman进行异步任务处理。centos
新的处理方式:
次控端调用前台接口上传图片,前台保存要上传的图片后,提早返回信息给次控端,接着,调用Gearman增长一个任务,而后,由Gearman自动指派任务给服务器进行任务处理。采用新的处理方式后,次控端操做体验更加快捷。
2、Gearman详细介绍
简介:
官网:http://gearman.org/
Gearman是一个分布式的程序框架。Gearman提供了一个通用的应用程序,能够工做在更加适合处理这项任务的其余计算机或其余处理器上。它容许并行处理,载入平衡处理,并且能够在不一样语言间进行调用。它能够应用于各类各样的应用场合。换句话说,它是一个进行分布式处理的强健系统。如下是关于Gearman的一些长处:
l 开源:彻底开源,免费的。
l 多语言:有许多语言接口,并且支持的语言数量一直在增长。
l 灵活:不依赖于任何特定的设计。
l 快速:简单的协议和接口,能够减小现有应用程序的开销。
l 嵌入:轻量,能够以最小的代价引入到现有程序。
l 没有单点故障:具备较强的容错性。
框架:
、
(摘自官网)
Gearman Client:提供客户端调用,API能够是多种语言,目前在智能建站里应用的是PHP语言
Gearman Job Server:调度者,负责把来自客户端的请求分发到不一样服务器或不一样处理器上的Worker。
Gearman Worker:负责任务处理,并返回结果。
说明:应用程序经过Client API调用建立客户端请求,Job Server把请求分发到不一样的worker上进行处理,Worker接收到请求并进行处理后返回结果。
如下是Gearman中三个基本模块的调用关系图:
(摘自官网)
Client与Worker是能够由不一样的语言来写的,例如:Client由PHP来写,Worker由C语言来写。这样就能够很方便地把不一样的语言编写的接口进行各自的接口封装。
无论是把Worker放到单独服务器,仍是放到集群服务器,Worker均可以正常运行。
Client发送任务到Job Server中,由Job Server负责调度,Job Server会自动检测空闲的Worker,并发送任务到这个空闲的Worker,Worker进行任务处理。所以,Gearman框架能够实现资源负载平衡。
Gearman框架具备很强的扩展性。这个框架支持多核心CPU。若是Worker所在的服务器太繁忙,能够把服务器的CPU换成更多核心的CPU,如16核CPU,这样就能够在这台服务器上建立16个Worker实例来进行处理。固然,Gearman也支持服务器的扩展,能够很方便地扩展出更多的Worker服务器来处理请求。惟一须要作的事情就是:启动新服务器,安装好Worker程序,并修改配置便可。
若是服务器挂掉了,Gearman会如何处理呢?咱们能够同时运行多个Job Server,Client和Worker链接到配置好的Job Server。若是这台Job Server出现故障,则配置到这台的Client和Worker会自动链接到另一台可用的Job Server。这里建议你们,至少要有两台以上的Job Server,利用冗余来提升系统的容错性。
安装:
Job Server (gearmand)
gearmand (C)
A job server written in C/C++ under the BSD license that contains all of the latest protocol additions. Development for this is very active, with threading, persistent queues, and pluggable protocols now supported. Replication and better statistics reporting are coming soon. This installs an executable calledgearmand
(usually in /usr/local/sbin). The C library, libgearman, is bundled in the same package.
./configure --prefix=/opt
安装报错:
checking whether the Boost::Program_Options library is available... yes
configure: error: Could not find a version of the library!
安装boost:
configure: error: could not find gperf
安装之:yum install gperf
(apt-get install gperf
Linux下生成hash函数代码的工具。)
configure: error: Unable to find libuuid
仍是错误。
所以,只有去官网下载:
http://sourceforge.net/projects/libuuid/
用源码安装方式安装。
而后,再次从新执行gearman目录下的./configure。呼呼~~~~~,终于再也不出错了,此次顺利执行完毕。
(能够加参数,如:./configure --with-sqlite3=/usr/local/sqlite3 --with-boost=/usr/local/boost-1.57 --with-boost-libdir=/usr/local/boost-1.57/lib
--with-memcached=[PATH]
absolute path to memcached executable
(若是报错libcurl
安装:
aptitude install libcurl4-openssl-dev
报错uuid错误:
libgearman/.libs/libgearman.so: undefined reference to `uuid_generate_time_safe@UUID_2.20'
libgearman/.libs/libgearman.so: undefined reference to `uuid_unparse@UUID_1.0'
collect2: error: ld returned 1 exit status
make[1]: *** [t/sqlite] Error 1\
须要葱这里 http://sourceforge.net/projects/e2fsprogs/files/e2fsprogs/v1.42.5/ 下载并安装e2fsprogs, 注意configure的参数必须是:./configure --prefix=/usr/local/e2fsprogs --enable-elf-shlibs,而后把uuid目录拷过去 cp -r lib/uuid/ /usr/include/ 和 cp -rf lib/libuuid.so* /usr/lib 以后make clean重试便可!
.安装e2fsprogs (必须用源码安装,yum安装的很差使)ubuntu好像不行。
./configure –enable-elf-shlibs make make install cp -r lib/uuid/ /usr/include/ cp -rf lib/libuuid.so* /usr/lib
)
安装 gearmand
后,构建 PHP 扩展。您能够从 PECL 获取这个 tarball,也能够从 Github 复制该存储库。
$ wget http://pecl.php.net/get/gearman-0.6.0.tgz |
有了这些代码后,就能够开始构建扩展了:
$ phpize |
./configure 后面能够设置php-config路径:
./configure --prefix=/opt --with-php-config=/usr/local/php/bin/php-config
http://ju.outofmemory.cn/entry/105792
仍是报错:
configure: error: Please install libgearman
咱们在安装gearman的时候,已经有libgearman了,可是在编译扩展的时候,却用额外安装的lib,在运行的时候,不免出现性能方面的问题
在./configure的时候指定下gearman的路径就是了,没必要下降额外安装libgearman及下降版本(http://blog.csdn.net/aidenliu/article/details/7406390)
./configure --prefix=/opt --with-php-config=/usr/local/php/bin/php-config --with-gearman=/opt/gearmand/
( 安装php扩展的时候,缺乏 libgearman ,这在安装gearman的时候应该已经安装好了,在安装gearman的时候./configure 不要加参数便可)
这个 Gearman 守护程序一般被安装在 /usr/sbin。能够从命令行直接启动此守护程序,也能够将这个守护程序添加到启动配置中,以便在机器每次重启时就能够启动这个守护程序。
接下来,须要安装 Gearman 扩展。打开 php.ini 文件(能够经过 php --ini
命令快速找到这个文件),而后添加代码行 extension = gearman.so
:
$ php --ini |
保存此文件。要想验证扩展是否启用,请运行 php --info
,而后查找 Gearman:
$ php --info | grep "gearman support" |
此外,还能够用一个 PHP 代码片断来验证构建和安装是否得当。将这个小应用程序保存到 verify_gearman.php:
<?php |
接下来,从命令行运行此程序:
$ php verify_gearman.php |
若是这个版本号与以前构建和安装的 Gearman 库的版本号相匹配,那么系统就已准备好了。
咱们前面提到过,一个 Gearman 配置有三个角色:
email_all
或analyze
。借助以下的命令行,能够当即体验 Gearman:
$ sudo /usr/sbin/gearmand --daemon |
gearman
运行一个 worker。这个 worker 须要一个名字并能运行任何命令行实用工具。例如,能够建立一个 worker 来列出某个目录的内容。-f
参数命名了该 worker 所提供的函数:
$ gearman -w -f ls -- ls -lh |
gearman
生成一个请求。一样,用 -f
选项来指定想要从中得到帮助的那个服务: $ gearman -f ls < /dev/null |
从 PHP 使用 Gearman 相似于以前的示例,唯一的区别在于这里是在 PHP 内建立 producer 和 consumer。每一个 consumer 的工做均封装在一个或多个 PHP 函数内。
清 单 1 给出了用 PHP 编写的一个 Gearman worker。将这些代码保存在一个名为 worker.php 的文件中。
1.Worker.php
<?php $worker= new GearmanWorker(); $worker->addServer(); $worker->addFunction("title", "title_function"); while ($worker->work()); function title_function($job) { return ucwords(strtolower($job->workload())); } ?>
清 单 2 给出了用 PHP 编写的一个 producer,或 client。将此代码保存在一个名为 client.php 的文件内。
<?php $client= new GearmanClient(); $client->addServer(); print $client->do("title", "AlL THE World's a sTagE"); print "\n"; ?>
[root@localhost code]# php Client.php
PHP Deprecated: GearmanClient::do(): Use GearmanClient::doNormal() in /opt/code/Client.php on line 4
All The Worlds's A Stags
把上面do改为doNormal
如今,能够用以下的命令行链接客户机与 worker 了:
$ php worker.php & |
这个 worker 应用程序继续运行,准备好服务另外一个客户机。
这个 worker 应用程序继续运行,准备好服务另外一个客户机。
在一个 Web 应用程序内可能有许多地方都会用到 Gearman。能够导入大量数据、发送许多电子邮件、编码视频文件、挖据数据并构建一个中央日志设施 — 全部这些均不会影响站点的体验和响应性。能够并行地处理数据。并且,因为 Gearman 协议是独立于语言和平台的,因此您能够在解决方案中混合编程语言。好比,能够用 PHP 编写一个 producer,用 C
、Ruby 或其余任何支持 Gearman 库的语言编写 worker。
一个链接客户机和 worker 的 Gearman 网络实际上可使用任何您能想象获得的结构。不少配置可以运行多个代理并将 worker 分配到许多机器上。负载均衡是隐式的:每一个可操做的可用 worker(多是每一个 worker 主机具备多个 worker)从队列中拉出做业。一个做业可以同步或异步运行并具备优先级。
Gearman 的最新版本已经将系统特性扩展到了包含持久的做业队列和用一个新协议来经过 HTTP 提交工做请求。对于前者,Gearman 工做队列保存在内存并在一个关系型数据库内存有备份。这样一来,若是 Gearman 守护程序故障,它就能够在重启后从新建立这个工做队列。另外一个最新的改良经过一个 memcached 集群增长队列持久性。memcached 存储也依赖于内存,但被分散于几个机器以免单点故障。
Gearman 是一个刚刚起步却颇有实力的工做分发系统。据 Gearman 的做者 Eric Day 介绍,Yahoo! 在 60 或更多的服务器上使用 Gearman 天天处理 600 万个做业。新闻聚合器 Digg 也已构建了一个相同规模的 Gearman 网络,天天可处理 400,000 个做业。Gearman 的一个出色例子能够在 Narada 这个开源搜索引擎(参见 参 考资料)中找到。
Gearman 的将来版本将收集并报告统计数据、提供高级监视和缓存做业结果等。为了跟踪这个 Gearman 项目,能够订阅它的 Google 组,或访问 Freenode 上它的 IRC 频道 #gearman
。
http://www.oschina.net/question/12_7687
安装参考:
http://blog.chinaunix.net/uid-27177626-id-4325909.html
一篇文章:
PHP利用Gearman实现异步/并行多进程处理数据http://www.zrwm.com/?p=888
Gearman是一个可进行任务调度分发,提供并行数据处理的分布式计算框架,支持多种编程语言.
它由三部分组成:
Gearman的一些使用场景:
下面的简单例子仅为说明PHP如何使用Gearman,不具有实际生产意义.
一个简单的worker:
[root@centos192 worker]# cat myworker.php <?php $worker = new GearmanWorker(); $worker->addServer('192.168.1.192', 4730); $worker->addFunction('sayhello', function(GearmanJob $job){ $name = $job->workload(); return "hello, " . $name; }); $worker->addFunction('logMsg', function(GearmanJob $job){ $msg = $job->workload(); file_put_contents(__DIR__ . '/Msg.log', $msg, FILE_APPEND); }); while ($worker->work()){ usleep(50000); }
以守护进程方式启动worker:
# nohup php myworker.php >/dev/null 2>&1 &
addFuntion另外方式:
$gmworker->addFunction("reverse", "reverse_fn");
function reverse_fn($job)
{
return strrev($job->workload());
}
一个发送任务处理请求的client:
[root@centos191 client]# cat myclient.php <?php $name = $argv[1]; if (empty($name)) { echo "Usage: $argv[0] {name}"; exit(1); } try { $client = new GearmanClient(); $client->addServer('192.168.1.192', 4730); } catch(Exception $e){ echo "oops", $e->getMessage(); exit(1); } // 同步处理(Blocking),返回直接的处理结果 $result = $client->doNormal('sayhello', $name); echo $result . PHP_EOL; // 异步处理(Non-Blocking),仅返回一个处理状态的句柄 $job_handle = $client->doBackground('logMsg', $name); echo $job_handle . PHP_EOL;
运行myclient.php:
[root@centos191 client]# php myclient.php "Jose" hello, Jose H:centos192:5
http://php.net/manual/zh/gearmanclient.donormal.php
GearmanClient::doNormal — Run a single task and return a result
public string GearmanClient::doNormal ( string , string [, string ] )
$function_name$workload$uniquefunction_name
由程序自动执行的已注册函数。
workload
被处理的序列化数据。
unique
用于标识特定任务的惟一性 ID。
一个发出并行处理任务请求的例子tasksclient:
[root@centos191 client]# cat tasksclient.php <php try { $client = new GearmanClient(); $client->addServer('192.168.1.192', 4730); } catch(Exception $e){ echo "oops", $e->getMessage(); exit(1); } $client->setCompleteCallback(function(GearmanTask $task){ echo 'Completed task:: id :', $task->unique(), ' , handled result:', $task->data(), PHP_EOL; }); $client->addTask('sayhello', 'Jose', null, 1); $client->addTask('sayhello', 'John', null, 2); $client->addTaskBackground('logMsg', 'Peter'); $client->runTasks();
运行tasksclient:
[root@centos191 client]# php tasksclient.php Completed task:: id :2 , handled result:hello, John Completed task:: id :1 , handled result:hello, Jose
我最开始没有修改addServer的ip,致使php taskslinet.php一直处于运行状态,没有结果输出。这说明只要不返回结果,程序一直运行。
查查当前注册的worker及function(显示格式:FD IP-ADDRESS CLIENT-ID : FUNCTION ...)
[root@centos192 worker]# (echo "workers"; sleep 0.1) | nc 127.0.0.1 4730 32 192.168.1.192 - : sayhello logMsg 33 127.0.0.1 - : .
查看当前队列状况(显示格式FUNCTION\tTOTAL\tRUNNING\tAVAILABLE_WORKERS):
[root@centos192 worker]# (echo "status"; sleep 0.1) | nc 127.0.0.1 4730 sayhello 0 0 1 logMsg 0 0 1 .
第一列是function名称,第2列显示队列中的任务数,第3列显示正在运行的任务数,第四列显示可用的worker数.
上面例子中直接启动worker脚本做为守护进程,没法监控到worker进程是否存活.
使用Unix进程监控supervisord则可轻松解决这个问题.
将以下配置添加到supervisord的配置中,便可实现由supervisord来启动和监控myworker.
[program:myworker] command=/usr/local/php5415/bin/php myworker.php process_name=%(program_name)s_%(process_num)02d ;修改numprocs便可同时开启多个worker进程 numprocs=1 directory=/data/www/gearman/worker autostart=true autorestart=true user=gearmand stopsignal=KILL
gearman安装后在bin目录下有2个程序gearman,gearmanadmin,它用来Run Administrative commands against a server.
Provice help about the program.
Create a function from the server.
Connect to the host
Port number or service to use for connection
Drop a function from the server.
Fetch the version number for the server.
Fetch the verbose setting for the server.
Status for the server.
Workers for the server.
Shutdown server.
bin目录下的gearman用来命令行操做命令。Command line client for Gearmand
Common options
Function name to use for jobs (can give many)
Job server host
Print this help menu
Gearman server port
Timeout in milliseconds
Create a pidfile for the process
In client mode run one job per line, in worker mode send data packet for each line
Same as -n, but strip off the newline
Client options
Run jobs in the background
Run jobs as high priority
Run jobs as low priority
Prefix all output lines with functions names
Send job without reading from standard input
Unique key to use for job
Worker options*
Number of jobs for worker to run before exiting
Run in worker mode
With gearman you can run client and worker functions from the command line.
The environmental variable GEARMAN_SERVER can be used to specify multiple gearmand servers. Please see the c:func:’gearman_client_add_servers’ for an explanation of the required syntax.
http://gearman.info 是一个gearman文档的网站,不错。
http://php.net/manual/zh/gearmanclient.donormal.php php官方关于gearman的文档。
很好的博客:http://www.livingelsewhere.net/tag/gearman/
http://www.php-oa.com/2010/09/05/perl-gearman-distributed.html
http://blog.chinaunix.net/uid-27177626-id-4325909.html
http://www.cppblog.com/guojingjia2006/archive/2013/01/07/197076.html
http://www.2cto.com/kf/201312/262636.html
http://www.cppblog.com/guojingjia2006/archive/2013/01/07/197076.html