当我们在shell里执行storm shell命令时会调用shell_submission.clj里的main函数。shell_submission.clj如下:

shell_submission.clj
;; ns函数声明一个命名空间“backtype.storm.command.shell-submission”
(ns backtype.storm.command.shell-submission
 ;; :import引用backtype.storm中的StormSubmitter类
 (:import [backtype.storm StormSubmitter])
 ;; :use引用backtype.storm thrift命名空间中的thrift、util、config和log,并建立连接,这样调用thrift、util、config和log中函数就可以直接使用函数名称不需要加完全限定名
 (:use [backtype.storm thrift util config log])
 ;; :require引用clojure.string,并使用别名str代替完全限定名clojure.string
 (:require [clojure.string :as str])
 ;; :gen-class生成java类
 (:gen-class))
 ;; storm shell命令所执行的main函数,gen-class的默认前缀"-",-main函数可以看成public函数,^String是类型提示符,用于声明参数tmpjarpath是一个字符串,-main函数可以接受多个实参,第一个参数赋值给tmpjarpath,其他参数全部保存在args中,args一个"序列"
 (defn -main [^String tmpjarpath & args]
 ;; conf绑定集群配置信息map,read-storm-config函数定义在backtype.storm.config命令空间,用于读取集群配置信息,返回包含集群配置信息的map,read-storm-config函数参见其定义部分
 (let [conf (read-storm-config)
       ;; 从集群配置信息中获取nimbus主机
       host (conf NIMBUS-HOST)
       ;; 从集群配置信息中获取nimbus thrift server的端口
       port (conf NIMBUS-THRIFT-PORT)
       ;; 调用StormSubmitter类的静态方法submitJar,将tmpjarpath所标识的jar文件上传到nimbus服务器上,jarpath保存jar文件在nimbus服务器上的路径,submitJar方法参见其定义部分
       jarpath (StormSubmitter/submitJar conf tmpjarpath)
       ;; concat函数将[host port jarpath]和args进行合并,并保存在args中
       args (concat args [host port jarpath])]
   ;; str/join将args中的参数用空格进行连接后,作为参数传递给exec-command!函数,执行jar文件中的main方法
   (exec-command! (str/join " " args))
   ))

当Clojure源文件做为脚本执行时,它们将在运行时被编译为java字节码。它们同样可以提前编译为java字节码(AOT编译)。这改善了Clojure应用的启动时间,并生产了可以运用于java中的.class文件。如果编译过的命名空间中拥有一个叫做-main的函数,那么它就能够作为一个Java应用运行。命令行参数会作为参数传递给这个函数。

read-storm-config函数
;; read-storm-config函数调用Utils类的readStormConfig方法读取集群配置信息,并过滤掉信息中非法配置
(defn read-storm-config
 []
 ;; readStormConfig方法参见其定义部分
 (let [conf (clojurify-structure (Utils/readStormConfig))]
   ;; 调用validate-configs-with-schemas函数验证配置信息的正确性并删除不正确的配置信息
   (validate-configs-with-schemas conf)
   conf))
readStormConfig方法
public static Map readStormConfig() {
       // 调用readDefaultConfig方法从defaults.yaml配置文件读取集群默认配置信息存入一个map对象ret中
       Map ret = readDefaultConfig();
       // confFile保存系统变量"storm.conf.file"的值,系统变量"storm.conf.file"保存了用户自定义配置文件的路径
       String confFile = System.getProperty("storm.conf.file");
       Map storm;
       // 如果没有用户自定义配置文件,那么调用findAndReadConfigFile方法读取"storm.yaml"配置文件,将配置信息保存在storm中,否则读取用户自定义配置文件
       if (confFile==null || confFile.equals("")) {
           storm = findAndReadConfigFile("storm.yaml", false);
       } else {
           storm = findAndReadConfigFile(confFile, true);
       }
       // 将"storm.yaml"配置文件或用户自定义的配置文件信息覆盖添加到默认配置信息ret中
       ret.putAll(storm);
       // 读取命令行提供的配置信息,并覆盖添加到之前的map对象中
       ret.putAll(readCommandLineOpts());
       // 返回保存了配置信息的map对象
       return ret;
   }
submitJar方法

submitJar方法调用了StormSubmitter类的重载方法submitJar

/**
    * Submit jar file
    * @param conf the topology-specific configuration. See {@link Config}.
    * @param localJar file path of the jar file to submit
    * @return the remote location of the submitted jar
    */
   public static String submitJar(Map conf, String localJar) {
       return submitJar(conf, localJar, null);
   }
重载方法submitJar

submitJar通过thrift client调用nimbus thrift server中的beginFileUpload函数获取目标路径,然后将jar上传到nimbus的目标路径上

;
           ) break;
               // 调用nimbus thrift server中的uploadChunk函数将jar文件上传nimbus服务器,uploadChunk函数参见其定义部分
               client.getClient().uploadChunk(uploadLocation, ByteBuffer.wrap(toSubmit));
           }
           // 调用nimbus thrift server中的finishFileUpload完成jar文件上传,finishFileUpload函数参见其定义部分
           client.getClient().finishFileUpload(uploadLocation);

if (listener != null) {
               listener.onCompleted(localJar, uploadLocation, totalSize);
           }

LOG.info("Successfully uploaded topology jar to assigned location: " + uploadLocation);
           // 返回jar文件上传nimbus的路径
           return uploadLocation;
       } catch(Exception e) {
           throw new RuntimeException(e);            
       } finally {
           client.close();
       }
   }

beginFileUpload函数
(beginFileUpload [this]
               ;; fileloc就是jar上传到nimbus上的目录"{storm.local.dir}/nimubs/inbox/stormjar-(uuid).jar",storm.local.dir是在配置信息中设置的
       (let [fileloc (str (inbox nimbus) "/stormjar-" (uuid) ".jar")]
         ;; (:uploaders nimbus)获取nimbus元数据中的TimeCacheMap,关于TimeCacheMap将在以后博客详细分析,将fileloc及其对应的FileOutputStream放入TimeCacheMap
         (.put (:uploaders nimbus)
               fileloc
               (Channels/newChannel (FileOutputStream. fileloc)))
         (log-message "Uploading file from client to " fileloc)
         ;; 返回上传路径
         fileloc
         ))

shell_submission.clj就分析到这里了,分析过程只列举了一些重要的函数,还有一些辅助函数没有列出,感兴趣的可以自己查看下。

storm shell命令源码分析-shell_submission.clj的更多相关文章

  1. Nimbus<二>storm启动nimbus源码分析-nimbus.clj

    nimbus是storm集群的"控制器",是storm集群的重要组成部分.我们可以通用执行bin/storm nimbus >/dev/null 2>&1 &a ...

  2. storm启动nimbus源码分析-nimbus.clj

    nimbus是storm集群的"控制器",是storm集群的重要组成部分.我们可以通用执行bin/storm nimbus >/dev/null 2>&1 &a ...

  3. storm操作zookeeper源码分析-cluster.clj

    storm操作zookeeper的主要函数都定义在命名空间backtype.storm.cluster中(即cluster.clj文件中).backtype.storm.cluster定义了两个重要p ...

  4. storm启动supervisor源码分析-supervisor.clj

    supervisor是storm集群重要组成部分,supervisor主要负责管理各个"工作节点".supervisor与zookeeper进行通信,通过zookeeper的&qu ...

  5. storm定时器timer源码分析-timer.clj

    storm定时器与java.util.Timer定时器比较相似.java.util.Timer定时器实际上是个线程,定时调度所拥有的TimerTasks:storm定时器也有一个线程负责调度所拥有的& ...

  6. supervisor启动worker源码分析-worker.clj

    supervisor通过调用sync-processes函数来启动worker,关于sync-processes函数的详细分析请参见"storm启动supervisor源码分析-superv ...

  7. worker启动executor源码分析-executor.clj

    在"supervisor启动worker源码分析-worker.clj"一文中,我们详细讲解了worker是如何初始化的.主要通过调用mk-worker函数实现的.在启动worke ...

  8. debug:am、cmd命令源码分析

    debug:am.cmd命令源码分析 目录 debug:am.cmd命令源码分析 am命令的实现 手机里的am am.jar cmd命令的实现 手机里的cmd cmd activity cmd.cpp ...

  9. memcached学习笔记——存储命令源码分析下篇

    上一篇回顾:<memcached学习笔记——存储命令源码分析上篇>通过分析memcached的存储命令源码的过程,了解了memcached如何解析文本命令和mencached的内存管理机制 ...

随机推荐

  1. [原创]java WEB学习笔记29:Cookie Demo 之自动登录

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  2. Python 3 udp 套接字

    Python 3 udp套接字 TCP是建立可靠连接,并且通信双方都可以以流的形式发送数据.相对TCP,UDP则是面向无连接的协议 使用UDP协议时,不需要建立连接,只需要知道对方的IP地址和端口号, ...

  3. 20145229 《Java程序设计》第10周学习总结

    20145229 <Java程序设计>第10周学习总结 教材学习内容总结 Java网络编程技术 数据交换 在计算机网络中,现在命名IP地址的规定是IPv4协议,该协议规定每个IP地址由4个 ...

  4. (转)Windows下面安装和配置MySQL(5.6.20)

    原文地址:http://www.cnblogs.com/qiyebao/p/3887055.html 1.首先到http://dev.mysql.com/ 上下载windows版mysql5.6免安装 ...

  5. Linux查看外网IP

    Linux查看外网IP curl cip.cc curl ifconfig.me curl ipinfo.io

  6. Hive- 表

    在hive中表的类型:管理表和托管表(外部表). 内部表也称之为MANAGER_TABLE,默认存储在/user/hive/warehouse下,也可以通过location指定:删除表时,会删除表的数 ...

  7. linux dd、echo 、watch、fuser命令

      一.dd命令 以数据流进行复制,cp命令则是以文件为单位进行复制 if=数据来源    of=数据存储目标    bs=# 复制的字节数   count=# 复制几个bs   seek=# 跳过多 ...

  8. 单机版 RedisUtils({基本操作封装工具类})【三】

    <!--集成的RedisJAR--> <!--引入jedis需的jar包--> <dependency> <groupId>redis.clients& ...

  9. Java丨验证码图片去除干扰像素,方便验证码的识别

    1.先来看看效果: 原图 除去干扰像素后 2.解析代码: 1).读取文件夹里面的图片 String fileName = "picture"; BufferedImage img ...

  10. linux命令学习笔记(40):wc命令

    Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出. .命令格式: wc [选项]文件... .命令功能: 统计指定文件中的字节数.字数 ...