storm任务提交流程

原文链接

源码查看的是1.0.3版本的jar

1、Client端提交Topology到nimbus
调用命令:

storm jar WordCount.jar storm.starter.storm.starter wordcount

实际上调用的是:

storm -client WordCount.jar storm.starter.storm.starter wordcount

2、通过TopologyBuilder将Spout和Bolt按照一定的逻辑顺序构建Topology程序

TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("spout", new RandomIntegerSpout());
builder.setBolt("partialsum", new StatefulSumBolt("partial"), Integer.valueOf(1)).shuffleGrouping("spout");
builder.setBolt("printer", new PrinterBolt(), Integer.valueOf(2)).shuffleGrouping("partialsum");
builder.setBolt("total", new StatefulSumBolt("total"), Integer.valueOf(1)).shuffleGrouping("printer");

3、通过调用TopologyBuilder的createTopology()方法,获取StormTopology实例对象。源码如下:

// 该方法用于创建Topology对象
public StormTopology createTopology() {
    ComponentCommon common;
    java.util.Map boltSpecs = new HashMap();
    java.util.Map spoutSpecs = new HashMap();
    maybeAddCheckpointSpout();
    for (String boltId : this._bolts.keySet()) {
      IRichBolt bolt = (IRichBolt)this._bolts.get(boltId);
      bolt = maybeAddCheckpointTupleForwarder(bolt);
      common = getComponentCommon(boltId, bolt);
      try {
        maybeAddCheckpointInputs(common);
        boltSpecs.put(boltId, new Bolt(ComponentObject.serialized_java(Utils.javaSerialize(bolt)), common));
      } catch (RuntimeException wrapperCause) {
        if ((wrapperCause.getCause() != null) && (NotSerializableException.class.equals(wrapperCause.getCause().getClass())))
        {
          throw new IllegalStateException("Bolt '" + boltId + "' contains a non-serializable field of type " + wrapperCause
            .getCause().getMessage() + ", which was instantiated prior to topology creation. " + wrapperCause
            .getCause().getMessage() + " should be instantiated within the prepare method of '" + boltId + " at the earliest.", wrapperCause);
        }

        throw wrapperCause;
      }
    }
    for (String spoutId : this._spouts.keySet()) {
      IRichSpout spout = (IRichSpout)this._spouts.get(spoutId);
      common = getComponentCommon(spoutId, spout);
      try {
        spoutSpecs.put(spoutId, new SpoutSpec(ComponentObject.serialized_java(Utils.javaSerialize(spout)), common));
      } catch (RuntimeException wrapperCause) {
        if ((wrapperCause.getCause() != null) && (NotSerializableException.class.equals(wrapperCause.getCause().getClass())))
        {
          throw new IllegalStateException("Spout '" + spoutId + "' contains a non-serializable field of type " + wrapperCause
            .getCause().getMessage() + ", which was instantiated prior to topology creation. " + wrapperCause
            .getCause().getMessage() + " should be instantiated within the prepare method of '" + spoutId + " at the earliest.", wrapperCause);
        }

        throw wrapperCause;
      }
    }

    // 把Spout和Bolt相关信息存放到map中,并返回Topology对象
    StormTopology stormTopology = new StormTopology(spoutSpecs, boltSpecs, new HashMap());

    stormTopology.set_worker_hooks(this._workerHooks);

    return stormTopology;
  }

4、开始提交任务,具体过程如下
(1)调用StormSubmitter.submitTopologyWithProgressBar(args[0], conf, builder.createTopology());提交任务(这种提交方式是集群下的提交)

submitTopologyWithProgressBar方法:
public static void submitTopologyWithProgressBar(String name, Map stormConf, StormTopology topology, SubmitOptions opts)
    throws AlreadyAliveException, InvalidTopologyException, AuthorizationException
  {
    // 在此方法中有调用了submitTopology方法
    submitTopology(name, stormConf, topology, opts, new ProgressListener()
    {
      public void onStart(String srcFile, String targetFile, long totalBytes) {
        System.out.printf("Start uploading file '%s' to '%s' (%d bytes)\n", new Object[] { srcFile, targetFile, Long.valueOf(totalBytes) });
      }

      public void onProgress(String srcFile, String targetFile, long bytesUploaded, long totalBytes)
      {
        int length = 50;
        int p = (int)(length * bytesUploaded / totalBytes);
        String progress = StringUtils.repeat("=", p);
        String todo = StringUtils.repeat(" ", length - p);

        System.out.printf("\r[%s%s] %d / %d", new Object[] { progress, todo, Long.valueOf(bytesUploaded), Long.valueOf(totalBytes) });
      }

      public void onCompleted(String srcFile, String targetFile, long totalBytes)
      {
        System.out.printf("\nFile '%s' uploaded to '%s' (%d bytes)\n", new Object[] { srcFile, targetFile, Long.valueOf(totalBytes) }); } } );
  }

(2) submitTopologyWithProgressBar方法中又调用了StormSubmitter的submitTopologyf方法。
submitTopology方法:

public static void submitTopology(String name, Map stormConf, StormTopology topology, SubmitOptions opts, ProgressListener progressListener)
    throws AlreadyAliveException, InvalidTopologyException, AuthorizationException
  {
    submitTopologyAs(name, stormConf, topology, opts, progressListener, null);
  }

(3)而在submitTopology方法又调用了submitTopology的submitTopologyAs方法
submitTopologyAs方法:

public static void submitTopologyAs(String name, Map stormConf, StormTopology topology, SubmitOptions opts, ProgressListener progressListener, String asUser)
    throws AlreadyAliveException, InvalidTopologyException, AuthorizationException, IllegalArgumentException
  {
 // 检查Stormconf必须是json-serializable Json序列化对象
 if (!(Utils.isValidConf(stormConf)))
      throw new IllegalArgumentException("Storm conf is not valid. Must be json-serializable");

    stormConf = new HashMap(stormConf);
    stormConf.putAll(Utils.readCommandLineOpts());
    Map conf = Utils.readStormConfig();
    conf.putAll(stormConf);
    // 获得命令行参数,并把它放到Stormconf中
    stormConf.putAll(prepareZookeeperAuthentication(conf));
    validateConfs(conf, topology);

    Map passedCreds = new HashMap();
    if (opts != null) {
      Credentials tmpCreds = opts.get_creds();
      if (tmpCreds != null)
        passedCreds = tmpCreds.get_creds();
    }

    Map fullCreds = populateCredentials(conf, passedCreds);
    if (!(fullCreds.isEmpty())) {
      if (opts == null)
        opts = new SubmitOptions(TopologyInitialStatus.ACTIVE);

      opts.set_creds(new Credentials(fullCreds));
    }
    try {
      // 判断nimbus是否为空,如果不为空,启动本地运行模式
      if (localNimbus != null) {
        LOG.info("Submitting topology " + name + " in local mode");
        if (opts != null) {
          localNimbus.submitTopologyWithOpts(name, stormConf, topology, opts);
        }
        else
          localNimbus.submitTopology(name, stormConf, topology);

        LOG.info("Finished submitting topology: " + name);
      } else {
        String serConf = JSONValue.toJSONString(stormConf);
        // 检查Topology的名称在集群上是否存在,如果存在抛出异常
        if (topologyNameExists(conf, name, asUser))
          throw new RuntimeException("Topology with name `" + name + "` already exists on cluster");

        // 调用submitJarAs方法提交jar文件
        String jar = submitJarAs(conf, System.getProperty("storm.jar"), progressListener, asUser);
        try { NimbusClient client = NimbusClient.getConfiguredClientAs(conf, asUser); Object localObject1 = null;
          try { LOG.info("Submitting topology " + name + " in distributed mode with conf " + serConf);
            if (opts != null) {
              client.getClient().submitTopologyWithOpts(name, jar, serConf, topology, opts);
            }
            else
              client.getClient().submitTopology(name, jar, serConf, topology);

            LOG.info("Finished submitting topology: " + name); } catch (Throwable localThrowable2) { } finally {
            if (client != null) if (localObject1 != null) try { client.close(); } catch (Throwable localThrowable3) { localObject1.addSuppressed(localThrowable3); } else client.close();  
          }
        } catch (InvalidTopologyException e) {
          LOG.warn("Topology submission exception: " + e.get_msg());
          throw e;
        } catch (AlreadyAliveException e) {
          LOG.warn("Topology already alive exception", e);
          throw e;
        }
      }
    } catch (TException e) {
      throw new RuntimeException(e);
    }
    invokeSubmitterHook(name, asUser, conf, topology);
  }

在submitTopology()方法中,做了一下工作:
1)检验Stormconf,必须是json-serializableJson的序列化对象 Utils.isValidConf(stormConf)

2)判断Topology的运行模式
//STONE_NOTE如果localNimbus不为空的话,调用本地模式运行 localNimbus.submitTopology(name,null,serConf,topology);

3)如果为分布式集群模式运行
//STONE_NOTE检测Topology的名称在集群上是否存在 topologyNameExists(client,conf,name)

//STONE_NOTE调用submitJar方法,提交jar文件
submitJar(client,conf);

//STONE_NOTE新的提交方式,携带opts参数 提交Topology任务
client.getClient().submitTopologyWithOpts(name,path,serConf,topology,opts);
最终任务提交完成!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值