php分布式gearman,大规模web架构gearman分布式处理应用案例

一. 场景分析 业务服务压力比较大,想把一些占用资源的功能异步到远程处理,比如记录业务日志,文件加密,文件分发到其他文件服务器节点上,检查文件服务器是否已同步,对用户上传的图片进行剪裁生成多份缩略图,视频转换,静态内容生成,清除缓存等等,这些请求耗时长,占用系统资源大,影响业务正常访问。这些问题会经常遇到的,如果这些任务都在用户请求过程中完成,服务器撑不撑得住暂不考虑,单凭用户体验角度考虑来说,那是难以忍受的。

二. 解决之道 对于这种需求,我们可以通过分布式计算,对任务进行拆分,转移到多台服务器上进行异步或同步处理。分布式消息队列有多种实现方式如

rabbitmq、

gearman等。 在这里主要说gearman---分布式处理系统。gearman由三部分组成:Job server,worker server,client server。 任务服务器job server运行这gearmand进程,来负责处理应用的远程调用请求,并且维护计算任务;工作服务器worker server负责向job server注册函数等待领取任务并执行实际的计算,然后将结果返回给job server;客户端client server提供gearman client API给应用程序调用,API支持多种语言如C、php、perl、python、mysql udf、java、ruby、go等等,主要是向job server添加任务, 流程图如下:

c744c1a2e4fdf8608e2c6aa198ef7ba6.png 客户端client server向gearman添加任务时,有三种模式: 1. 同步顺序处理 相当于消息队列,先进先出。 2. 同步并行处理 这种模式会阻塞后面的运行,将互不依赖的任务并行处理,大大缩短整体处理时间。 3. 异步后台处理 将耗时任务交给后台处理,不阻塞当前进程。 本站点ttlsa.com关于

gearman介绍以及应用 参见:http://www.ttlsa.com/?s=gearman

关于PHP实现异步操作的研究 参见:http://www.ttlsa.com/html/1720.html

gearman安装 参见:http://www.ttlsa.com/html/663.html

三. 应用实例 需要安装的模块有Mail::SendEasy、Gearman::Worker、Gearman::Client、JSON。

# perl -MCPAN -e 'install Mail::SendEasy Gearman::Worker Gearman::Client JSON' 或通过

cpanm来安装,参见:http://www.ttlsa.com/html/2030.html 在使用异步处理之前,当我们要发送邮件时,会直接这么写,代码如下:

use strict;

use Mail::SendEasy ;

my $mail = new Mail::SendEasy(

smtp => 'smtp.ttlsa.com' ,

user => 'service@ttlsa.com' ,

pass => 'QQ_qun:39514058',

);

my $status = $mail->send(

from => 'service@ttlsa.com' ,

from_title => $mail_title ,

to => $mail_to ,

subject => $mail_subject ,

msg => $mail_msg ,

html => "$mail_msg" ,

);

if (!$status) { print $mail->error ;} 这存在一个问题, 会长期阻塞在send函数,而无限制等待下去, 直到超时,很可能会拖垮服务器的。我们可以使用gearman,来改变这种发送邮件的方式。第一步,创建一个worker实例SENDMAIL,并向job server注册,等待接收任务并执行发送邮件的操作。第二步,客户端只需要将发送邮件的任务丢给job server便退出,没你什么事了。上代码: # vim work_SENDMAIL.pl

###################################

### author: www.ttlsa.com###

### QQ群: 39514058###

### E-mail: service@ttlsa.com###

###################################

use strict;

use Mail::SendEasy ;

use Gearman::Worker;

use JSON;

use Data::Dumper;

my $gearman_server='127.0.0.1:4730';

my $worker=new Gearman::Worker;

$worker->job_servers($gearman_server);

$worker->register_function(SENDMAIL=>\&sendmail);

$worker->work while 1;

sub sendmail{

my $job=shift;

my $param=$job->arg;

my $json = JSON->new->allow_nonref;

my $hash_ref=$json->decode($param);

my $addr=$hash_ref->{'email'};

my $subject=$hash_ref->{'subject'};

my $msg=$hash_ref->{'msg'};

my $mail = new Mail::SendEasy(

smtp => 'smtp.ttlsa.com' ,

user => 'service@ttlsa.com' ,

pass => 'QQ_qun:39514058',

);

my $status = $mail->send(

from => 'service@ttlsa.com' ,

from_title => $subject ,

to => $addr ,

subject => $subject ,

msg => $msg ,

html => "$msg" ,

);

if (!$status) { print $mail->error ;}

} # vim gearman_client.pl

###################################

### author: www.ttlsa.com###

### QQ群: 39514058###

### E-mail: service@ttlsa.com###

###################################

use strict;

use Gearman::Client;

use JSON;

my $gearman_server="127.0.0.1:4730";

my $worker='SENDMAIL';

my $data={};

$data->{'subject'} = "www.ttlsa.com --- Operation & Maintenance of Time To Live";

$data->{'msg'} = "Date: gettime() 如何记住本站点ttlsa.com拆开便是ttl(time to live)sa(system admin).com,本站点坚持每日更新,欢迎纠错、评论以及转载.";

$data->{'email'} = '710117291@qq.com';

my $json = JSON->new->allow_nonref;

my $param=$json->encode($data);

gearman_add_job($gearman_server,$worker,$param,2);

sub gearman_add_job {

my $server=shift;

my $function_name=shift;

my $function_param=shift;

my $level=shift or 1;

my $gearman_client = Gearman::Client->new;

$gearman_client->job_servers($server);

if($level == 1){

my $result = $gearman_client->do_task($function_name,\$function_param,{});

}

elsif($level == 2){

my $result = $gearman_client->dispatch_background($function_name, \$function_param,{});

}

}

sub gettime {

my @time=(localtime)[5,4,3,2,1,0];

$time[0]+=1900;

$time[1]+=1;

return sprintf("%04u-%02u-%02u %02u:%02u:%02u",@time);

} 完成上面的改造不要认为解决了发送邮件会长期阻塞在send函数,而无限制等待下去的问题了。这其实只是解决了一部分,还有一个问题需要考虑进去,既然采用了异步方式,那么应用程序是不知道邮件是否发送成功的,因此需要记录任务执行的结果,可以将结果写入数据库,定期的对发送失败的邮件进行再次发送,或写个异常处理的worker,捕获发送邮件异常,进行多次尝试发送。 这种方案是我在捕获数据库备份过程中失败时,发邮件报警的应用。

mongodb备份与恢复(下)  http://www.ttlsa.com/html/2052.html中提供的备份脚本就有应用到,只是删掉了该功能,哈,网友们自己去实现咯。 通过这样的异步任务处理,可以很好的解决前面场景提到的问题,完全取决于如何应用gearman了。如有更好的应用可以相互交流。 如需转载请注明出处:http://www.ttlsa.com/html/2839.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值