storm topology優化之lib庫分離
最近在基于storm做實時分析統計工作,每次將topology打包上傳到服務器上,都是一個艱難的事情,原因有里兩個:
1,因為一個topology,如果引用了第三方包,體積就會變大,上傳時間隨著包體成正比例。
2,加大Nimbus、Supervisor、Zookeeper的網絡壓力。
先簡單描述storm運行一個topology的流程:
1,提交topology.jar后,jar包上傳到Nimbus的${storm.local.dir}/inbox目錄中,之后把該jar包序列化到stormdist目錄中。
2,Nimbus根據topology設定的spout、bolt數分配worker,nimbus會根據spout、bolt的數量盡量平均分配到每個worker
3,nimbus將任務信息(包括代碼)提交到zookeeper集群上,保存當前topology與所有worker進程的心跳信息(workerbeats節點);同時將topology的任務分配信息、代碼存儲目錄、任務之間的關聯關系保存到assignments節點下。
4,supervisor不斷輪詢zookeeper的assignments節點上,是否有自己的任務。當輪詢到有自己的任務,將會任務信息(包括代碼)。
5,topology開始執行之后,spout不斷發stream流,bolt不斷接受stream流。如果執行過程中,某個worker多次執行失敗,supervisor會發揮給nimbus重新調度分配。
上述5步中,1、3、4都涉及到代碼的網絡傳輸。假如topology包體很大的話,并且分配的worker比較多,那傳輸包體的瞬時帶寬就很高。
利用maven打包優化
mvn 打包時,配置classpathPrefix來指定所有依賴JAR文件的前綴,即在運行時,添加一個額外的ClassPath。然后在storm集群,新建剛剛指定的classpathPrefix目錄,將topology所依賴的包都放進去。完成后,當我們打包時,只要將具體的業務代碼上傳就可以。
示例:
在pom文件下添加如下配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.4</version> <configuration> <archive> <addMavenDescriptor>false</addMavenDescriptor> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>YOUR_LIB_PATH</classpathPrefix> </manifest> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.4</version> <configuration> <!-- 配置assembly組件 --> <descriptors> <descriptor>package.xml</descriptor> </descriptors> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin>
將上面的YOUR_LIB_PATH替換成你的目錄。
再在項目下添加package.xml文件(上面的pom.xml中指定的),文件內容如下:
<assembly>
<id>bin</id>
<!-- 最終打包成一個用于發布的zip文件 -->
<formats>
<format>zip</format>
</formats>
<!-- Adds dependencies to zip package under lib directory -->
<dependencySets>
<dependencySet>
<!--
不使用項目的artifact,第三方jar不要解壓,打包進zip文件的lib目錄
-->
<useProjectArtifact>false</useProjectArtifact>
<outputDirectory>lib</outputDirectory>
<unpack>false</unpack>
</dependencySet>
</dependencySets>
<fileSets>
<!-- 把項目自己編譯出來的jar文件,打包進zip文件的根目錄 -->
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory></outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>