在Storm(五)第一個集群Topology中用如下的命令行向集群提交了Topology:
storm jar cluster-topology-1.0-SNAPSHOT.jar com.quiterr.ExclamationTopology
但是在項目中需要動態自動化提交Topology,也就是通過代碼來提交Topology。
這里仍然以ExclamationTopology為例來說明,不過要對ExclamationTopology做一些改造,要把ExclamationTopology中的Bolt單獨提出來做一個項目(或模塊),創建Topology相關的代碼做成另一個項目。
一、Topology項目(后續以項目名dynamic-submit-classes來敘述)
這個項目用來放Topology自身相關的東西,包括Spout、Bolt等,實際項目中可以很復雜,但是在這個例子中很簡單,因為Spout是Storm核心庫提供的,而Bolt只有一個。
(一)pom文件
<dependencies>
<dependency>
<groupId>org.apache.storm</groupId>
<artifactId>storm-core</artifactId>
<version>${storm.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
極簡單,沒什么好說的。
(二)ExclamationBolt
這個項目只有一個類ExclamationBolt,從ExclamationTopology里邊copy出來的。
public class ExclamationBolt extends BaseRichBolt {
OutputCollector _collector;
public void prepare(Map conf, TopologyContext context, OutputCollector collector) {
_collector = collector;
}
public void execute(Tuple tuple) {
_collector.emit(tuple, new Values(tuple.getString(0) + "!!!"));
_collector.ack(tuple);
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
}
(三)安裝到本地
使用mvn install
命令安裝到本地,因為下一個項目要用到本項目。
(四)部署到Storm服務器
把生成的jar包放到Storm服務器上,這里放的路徑是/home/app/test
本項目源代碼:https://github.com/quiterr/storm-test/tree/master/dynamic-submit-classes
二、創建Topology項目(后續以項目名dynamic-submit來敘述)
用Spring Boot做一個RESTful API,專門用來接收創建Topology的請求,創建完畢后向集群提交Topology。
(一)pom文件
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--配置處理器,會在編輯配置文件的時候智能提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!--自己實現的topology所在的庫-->
<dependency>
<groupId>com.quiterr</groupId>
<artifactId>dynamic-submit-classes</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.3.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
除了Spring Boot相關的依賴,就是上一個項目的依賴。
(二)SubmitController
SubmitController接收一個topologyName參數,然后創建topology,最后提交到集群。代碼中有一行指明了topology所在的位置:System.setProperty("storm.jar", "/home/app/test/dynamic-submit-classes-1.0-SNAPSHOT.jar");
@RestController
public class SubmitController {
@RequestMapping(value = "/topology/create", method = RequestMethod.POST)
private boolean create(@RequestBody String topologyName){
Config conf = new Config();
conf.setDebug(true);
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("word", new TestWordSpout(), 10);
builder.setBolt("exclaim1", new ExclamationBolt(), 3).shuffleGrouping("word");
builder.setBolt("exclaim2", new ExclamationBolt(), 2).shuffleGrouping("exclaim1");
System.setProperty("storm.jar", "/home/app/test/dynamic-submit-classes-1.0-SNAPSHOT.jar");
try {
StormSubmitter.submitTopology(topologyName, conf, builder.createTopology());
} catch (AlreadyAliveException e) {
e.printStackTrace();
} catch (InvalidTopologyException e) {
e.printStackTrace();
} catch (AuthorizationException e) {
e.printStackTrace();
}
return true;
}
}
本項目源代碼:https://github.com/quiterr/storm-test/tree/master/dynamic-submit
三、測試和說明
把dynamic-submit-1.0-SNAPSHOT.jar和dynamic-submit-classes-1.0-SNAPSHOT.jar都放到Storm服務器上后,用java -jar dynamic-submit-1.0-SNAPSHOT.jar
啟動第一個項目,然后用一個RESTful的測試客戶端發請求即可。
有個問題:topology被提交到哪里了?
在Storm基礎(三)配置這篇文章里提到過,如果沒有定義storm.yml文件,就會使用Storm核心庫中自帶的default.xml文件,默認情況下topology就會提交到本地,這就是一定要把程序放到Storm所在的服務器上的原因。
四、用代碼遠程提交
能不能不把topology傳到服務器上,就在本地提交呢?
理論上是可以的。
1.把dynamic-submit-classes-1.0-SNAPSHOT.jar放到dynamic-submit工程目錄下。
2.StormSubmitter類中設置環境變量:System.setProperty("storm.jar", "dynamic-submit-classes-1.0-SNAPSHOT.jar");
3.dynamic-submit加一個storm.yml配置文件,內容像這樣:
########### These MUST be filled in for a storm configuration
storm.zookeeper.servers:
- "172.19.3.147"
- "172.19.3.148"
- "172.19.3.149"
nimbus.seeds: ["172.19.3.147"]
storm.local.dir: "/data/storm_local"
supervisor.slots.ports:
- 6700
- 6701
- 6702
- 6703
- 6704
- 6705
- 6706
- 6707