• Feeds

  • 利用Gearman来实现远程监控与管理

    Gearman是一个分发任务的程序框架,可以用在各种场合,与Hadoop相比,Gearman更偏向于任务分发功能。它的任务分布非常简单,简单得可以只需要用脚本即可完成。Gearman最初用于LiveJournal的图片resize功能,由于图片resize需要消耗大量计算资源,因此需要调度到后端多台服务器执行,完成任务之后返回前端再呈现到界面。

    gearman

    Gearman分布式任务实现原理上只用到2个字段,function name和data。function name即任务名称,由client传给job server, job server根据function name选择合适的worker节点来执行。data通常为执行任务所需的自定义的内容,比如简单的做法可以把需要执行的脚本当成data即可(当然要注意其中的安全防范)。如果有多个worker可以处理同一个function name, 则job server会自动分配一个。当用于远程监控场景时,我们可以让每个worker注册成不同的业务名称,以达到方便控制每台worker节点的目的。

    下面介绍Gearman实践中可用于多服务器管理的一些小功能,如果你的服务器有多台,重复执行命令过于繁琐,那可以借助下面一些脚本来完成一些有趣的功能。比如要实时看到所有服务器上的 netstat -nat | grep 80, 按下面步骤搭好环境之后,只需要几行脚本代码即可实现。

    1. 安装gearman
    最早的gearman是perl版的,由于国内开发人员对perl熟悉的不多,所以推荐安装C版本
    http://gearman.org/index.php?id=download
    解开后 ./configure; make; make install 即可

    2. 启动 job server
    cd sbin; ./gearmand -d

    3. 到 worker 节点启动 worker

    先按步骤1在worker机上安装 gearman, 然后创建一个执行worker的python脚本。

    #!/usr/bin/env python
    import os
    
    def main():
        cmd = raw_input()
        print os.popen(cmd).read()
    
    if __name__ == "__main__":
        main()

    cd bin; ./gearman -w -h <job_server_ip> -f server1 — ./monitor.py

    4. 通过远程 web 管理
    JSP示例:

    <%@ page language="java" import="java.util.*,java.util.concurrent.*,
    org.gearman.client.*,org.gearman.common.*"%><%!
            private static String host = "192.168.1.1";
            private static int port = 4730;
            public String testGearman(String func, String data) {
                    byte[] input = data.getBytes();
                    String uniqueId = null;
    
                    GearmanJobServerConnection conn =
                        new GearmanNIOJobServerConnection(host, port);
                    GearmanClient client = new GearmanClientImpl();
                    client.addJobServer(conn);
                    GearmanJob job = GearmanJobImpl.createJob(func, input, uniqueId);
                    Future<GearmanJobResult> f = client.submit(job);
                    GearmanJobResult jr = null;
                    String result = null;
                    try {
                            jr = f.get(3, TimeUnit.SECONDS);
                            result = new String(jr.getResults());
                    } catch (Exception e) {
                            result = e.getMessage();
                    }
    
                    client.shutdown();
                    return result;
            }
    %><%
    out.println(testGearman("test", "netstat -nat | grep 80");
    %>

    PHP示例:

    # Create our client object.
    $client= new GearmanClient();
    
    # Add default server (localhost).
    $client->addServer();
    
    echo "Sending job\n";
    
    # Send reverse job
    $result = $client->do("server1", "netstat -nat | grep 80");
    if ($result)
      echo "Success: $result\n";

    如想及时阅读Tim Yang的文章,可通过页面右上方扫码订阅最新更新。

    « | »

    20 Comments  »

    1. 我觉得这种东西适合那种不需要返回结果的计算,如果要等等结果返回的话,通过网络传输启不速度更慢,响应能力反而更低了~

    2. 我觉得返回并不是问题,很多场合的情况下,我们处理任务,肯定放在一台任务服务器上跑的。那肯定会新启一个线程来异步等待。并不会用一个线程在那个地方等着。如果一个线程等着,那我们就不需要任务服务器了。

    3. Tim

      对于gearman应用等待返回肯定是要的,否则还不如用MQ了。
      1. 通常gearman部署是不跨IDC的,排除网络延迟因素,如果有延迟也是worker程序造成。
      2. 如果worker程序存在卡的问题,client可以加超时,如例子所示。
      jr = f.get(3, TimeUnit.SECONDS);在实践中很少出现超时的情况。

    4. xLight

      如果服务器都开着ssh,
      简单写个脚本循环执行就好了啊

    5. Tim

      @xLight ssh通常需要交互输入密码,同时直接用ssh shell交互也容易造成安全隐患。
      使用gearman, worker script可以只接收指定的协议,比如用自定义的A/B/C/D来代替具体的执行命令。
      另外易用性上gearman不管是web client还是worker都比配置ssh更简单。

    6. xLight

      @Tim
      看来我是ssh权限用惯了,呵呵
      没考虑你说的这种应用场景

    7. balancer 不知道好不好用

    8. Robin

      Hi Tim,我正在尝试这种方案,不过发现向Job Server发送的指令只会在某一台Worker上去执行?并不会到所有的Worker上执行?

    9. Robin

      呃。看明白你的意思了,将每个worker注册成不同的名称。

    10. leiyang

      gearman不是用来解决者问题的……

      让这么多不会coding的SA情何以堪……

      SSH-AGENT + SSH-ADD + 有passphrase的private key就简单了

      连perl都不用装

    11. wss8848

      自学得不错,你不会是扫描进来的吧~~?

    12. wss8848

      字写的不错,呵呵,打错了

    13. wellhome

      如果执行的东西超过2分钟。
      web client会一直keep connected知道等到返回结果?

    14. billy

      对于各种任务的返回结果需要自定义,有些较复杂,如数据量在某一时段较大时,另对WORK执行范围也需要配置好,以免发生错误

    15. 晓梦

      这个和func比有什么优势略势呢?

    16. peter

      个人觉得:
      1.返回结果,是一个复杂任务需要利用多台机子的处理能力,或者均衡负载,或者利用并行完成复杂的操作步骤,而这些步骤可以均衡负载处理,map到多个机子并行处理,之后reduce返回结果,比如一个sphinx搜索引擎,一个完整的搜索过程可能对这个引擎来说是几步,得到ids collection,查询多个data source,最后得到结果,这几个过程可以并行处理。
      2不返回结果,是某些任务直接扔给后端处理,并且保证大部分成功,或者失败也能够跟踪处理,比如推送服务或者邮件服务。

    17. 基本找不到生产环境的示例,都说得太简单了。

    Leave a Comment