gearman入门与实践

一、Gearman的概念

    Gearman提供了一种通用的应用框架,能够分发任务到不同的机器或者进程当中。 它允许进行并行工作、负载均衡,以及在不同程序语言之间进行函数调用。Gearman能够应用的领域非常广泛,从高可用的网站到数据库的备份。总之,Gearman就是负责分发处理的中枢系统。它的特点包括:

  1、开源。

  2、多语言。

  3、灵活。

  4、可嵌入。

  5、无单点风险。

 

二、Gearman 的工作机制。

   gearman的工作机制

 

  gearman由 Client、Worker、JobServer三部分组成。 client的作用是创建一个job并传递给jobserver。Jobserver会选择一个合适的worker节点并将job指派给它。Worker会处理来自client的job请求,并将结果通过jobserer返回给client。Gearman提供了client和worker的api,用来和jobserver通信。worker和client通过socket与jobserver通信。

 

三、gearmand的安装部署。

   gearman jobserver 的下载安装步骤。         

tar xzf gearmand-X.Y.tar.gz

cd gearmand-X.Y

./configure

make

make install

 

  启动jobserver守护进程。

 

gearmand -d

 

下面是一些更多的启动参数。

-b, --backlog=BACKLOG      Number of backlog connections for listen.
 -d, --daemon               Daemon, detach and run in the background.
 -f, --file-descriptors=FDS Number of file descriptors to allow for the process
                            (total connections will be slightly less). Default
                            is max allowed for user.
 -h, --help                 Print this help menu.
 -j, --job-retries=RETRIES  Number of attempts to run the job before the job
                            server removes it. Thisis helpful to ensure a bad
                            job does not crash all available workers. Default is
                            no limit.
 -l, --log-file=FILE        Log file to write errors and information to. Turning
                            this option on also forces the first verbose level
                            to be enabled.
 -L, --listen=ADDRESS       Address the server should listen on. Default is
                            INADDR_ANY.
 -p, --port=PORT            Port the server should listen on.
 -P, --pid-file=FILE        File to write process ID out to.
 -r, --protocol=PROTOCOL    Load protocol module.
 -q, --queue-type=QUEUE     Persistent queue type to use.
 -t, --threads=THREADS      Number of I/O threads to use. Default=0.
 -u, --user=USER            Switch to given user after startup.
 -v, --verbose              Increase verbosity level by one.
 -V, --version              Display the version of gearmand and exit.

libdrizzle Options:

     --libdrizzle-host=HOST         Host of server.
     --libdrizzle-port=PORT         Port of server.
     --libdrizzle-uds=UDS           Unix domain socket for server.
     --libdrizzle-user=USER         User name for authentication.
     --libdrizzle-password=PASSWORD Password for authentication.
     --libdrizzle-db=DB             Database to use.
     --libdrizzle-table=TABLE       Table to use.
     --libdrizzle-mysql             Use MySQL protocol.

libmemcached Options:

     --libmemcached-servers=SERVER_LIST List of Memcached servers to use.

libsqlite3 Options:

     --libsqlite3-db=DB       Database file to use.
     --libsqlite3-table=TABLE Table to use.

libpq Options:

     --libpq-conninfo=STRING PostgreSQL connection information string.
     --libpq-table=TABLE     Table to use.

http Options:

     --http-port=PORT Port to listen on.

 

  Gearmand的队列。

      client创建job任务之后, 会传递给jobserver服务器, jobserver中会存在一个queue,用来存放job任务。每个worker会从queue中领取任务执行。

默认情况下,job queue会存在于内存中,也就是说, 一旦服务器重启,将会丢失。

  持久化队列。

      gearman提供了实现将队列持久化的方法,目前支持drizzle/mysql, sqllite, postgrel,memcache等数据库持久化模块。

  开启方法:

   

gearmand -q libdrizzle --libdrizzle-host=10.0.0.1 --libdrizzle-user=gearman \
                       --libdrizzle-password=secret --libdrizzle-db=some_db \
                       --libdrizzle-table=gearman_queue --libdrizzle-mysql

 

 四、Gearman 的Client和Worker API。

   gearman支持多种api类型,例如 C、PHP、Python、Perl、Java、Lisp

   gearman的Client 创建 Job 需要两个主要参数, funcname和data。其中funcame代表该Job注册的处理方法名,会调用worker中相同方法名的处理函数。 data表示job的具体内容,传递给worker使用。

   gearman的Worker 创建处理函数也需要两个参数, funcname和function。其中function表示处理函数。

   以php举例。

   worker的代码如下:   

<?php
$worker= new GearmanWorker();
$worker->addServer();
$worker->addFunction("reverse", "my_reverse_function");
while ($worker->work());
 
function my_reverse_function($job)
{
  return strrev($job->workload());
}
?>

 

  worker注册了一个reverse函数,对字符串进行反转。

  启动worker命令: 

$ php worker.php

 

  client的代码如下: 

<?php
$client= new GearmanClient();
$client->addServer();
print $client->do("reverse", "Hello World!");
?>

 client调用了reverse方法,并传递一个hello world! 字符串。
 执行命令: 

$ php client.php
!dlroW olleH

 

 五、一个实际应用例子。

     我们来看一个处理图片的集群。

     大家都知道,处理图片常用的软件是ImageMagick,但是该软件运行时,对CPU消耗极大。所以单机的情况下,当并发数提高时, 负载就会显著增加。因此,需要搭建一个集群,将处理任务分派到多个worker上。

     client和worker的API都采用python脚本。 图片处理软件使用imagemagick。

    

  我们先来看一下client的代码, image_client.py

import gearman;
import tornado.web;
import tornado.ioloop;
import json;
import cPickle

class MainHandler(tornado.web.RequestHandler):
        def get(self):
                user = self.get_argument("user","");   
                self.write("You requested the main page. user=" + user);
        def post(self):
                files = self.request.files;
                instrList = self.get_argument("instrList","");        
                print instrList;
                sendjob(files, instrList);               
               

gm_client = gearman.GearmanClient(['127.0.0.1:4730']);

def sendjob(files,instrList):
        instrDic = {};
        instrDic["files"] = files;
        instrDic["instrList"] = instrList;
            
        completed_job_request = gm_client.submit_job("dealImage", cPickle.dumps(instrDic));
        print "state:",completed_job_request.state, ", result:", completed_job_request.result;


application = tornado.web.Application([
    (r"/", MainHandler),
]);

application.listen(8888);
tornado.ioloop.IOLoop.instance().start();

 

接着,我们看一下worker代码,image_worker.py

#!/usr/bin/python
import gearman;
import json;
import os;
import datetime;
import random;
import cPickle
def convert_photo_func(source, dest, width, height):
        command="convert " + source + " -resize " + width + "x" + height + " " + dest;     
        status = os.system(command);
        return status;

def cut_photo_func(source, dest, coord_x, coord_y, width, height):
        command = "convert " + source + " -crop " + width + "x" + height + "+" + coord_x + "+" + coord_y + " " + dest;      
        status = os.system(command);
        return status;


def deal_img(gearman_worker, gearman_job):
        data = gearman_job.data;            
        instrDic = cPickle.loads(data);      
        statuslist = [];
        fileList = instrDic.get("files").get("files");
        instrList = instrDic.get("instrList");
       
        file = fileList[0];
        filename = file["filename"];
        filebody = file["body"];
        file_content_type = file["content_type"];
        image_ext = ".jpg";
      
        if file_content_type == 'image/png':
                image_ext = ".png";
        millstime = datetime.datetime.now().microsecond;
        randomint = random.randint(1,100000);
        source_image_path = "/home/chen-wei/img/source/";
        source_file = str(millstime) + str(randomint) + image_ext;
     
        if os.path.exists:
                os.mkdir(source_image+path);
        fd = open(source_image_path + source_file, 'w');
        fd.write(filebody);
        fd.close();

        for instr in instrList:
                print instr;
                operator = instr.get("operator");
                source = instr.get("source");
                dest = instr.get("dest");
                width = instr.get("width");
                height = instr.get("height");
                coord_x = instr.get("coord_x", "");
                coord_y = instr.get("coord_y", "");
                print source,coord_x, coord_y;
                status = -1;
                if operator == 'convert':
                        status = convert_photo_func(source, dest, width, height);
                        print "status=",status;
                elif operator == 'cut':
                        status = cut_photo_func(source, dest, coord_x, coord_y, width, height);
                        print "status=",status;
                statuslist.append(status);

        return str(statuslist);

gm_worker = gearman.GearmanWorker(['127.0.0.1:4730']);

gm_worker.register_task('dealImage', deal_img);

gm_worker.work();

 

启动worker守护进程

./image_worker.py

执行client调用

./image_client.py

 

处理结果:

执行完./image_client.py 之后,我们看到多了2张图片。

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/mikojordan/archive/2013/04/26/3043901.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值