基本執(zhí)行流程
以SequenceTopology為例加匈,其加載流程為:
- 用戶提交拓?fù)涞臅r(shí)候,會(huì)先將自己的代碼打成jar包淋叶,通過nimbus提交拓?fù)涞郊?/li>
- nimbus執(zhí)行jar時(shí)調(diào)用StormSubmitter.submitTopology阎曹,通過TopologyBuilder來創(chuàng)建拓?fù)涞幕窘Y(jié)構(gòu)(即為spout和bolt創(chuàng)建了對象實(shí)例),并設(shè)置一些相關(guān)的conf
- 接著將創(chuàng)建出來的拓?fù)鋵ο筮M(jìn)行序列化,通過nimbus調(diào)度再提交到各個(gè)機(jī)器上
- 執(zhí)行worker的時(shí)候芬膝,會(huì)再先將拓?fù)涞南嚓P(guān)對象反序列化并加載望门,然后執(zhí)行
component(spout/bolt)序列化和反序列化
由于整個(gè)拓?fù)湎嚓P(guān)的對象都要被序列化,這意味著锰霜,component實(shí)現(xiàn)類必須是可序列化的筹误,進(jìn)一步意味著,spout/bolt的類屬性也必須是可序列化的癣缅。除非:
- spout/bolt的成員變量設(shè)置了transient/static厨剪,這樣的變量將不會(huì)被序列化。
- 屬性值為null友存,未被初始化祷膳。
否則提交后可能會(huì)出現(xiàn)對象不可反序列化的異常。
component(spout/bolt)構(gòu)造和執(zhí)行順序
- component構(gòu)造方法的執(zhí)行時(shí)間屡立,發(fā)生在創(chuàng)建對象的時(shí)候直晨,即提交拓?fù)渲啊?/li>
- 若component構(gòu)造方法初始化一些跟環(huán)境相關(guān)的變量(如連接DB),這時(shí)有可能是會(huì)有問題的膨俐。 因此勇皇,建議是放在spout.open/bolt.prepare方法中執(zhí)行這些動(dòng)作。
- worker執(zhí)行的時(shí)候焚刺,僅純粹地執(zhí)行對象反序列化敛摘,這時(shí)不會(huì)再調(diào)用構(gòu)造函數(shù)。
spring場景下的初始化
- 任何場景下乳愉,對環(huán)境相關(guān)的變量兄淫,都應(yīng)該在spout.open/bolt.prepare中來初始化
- 建議上述方法中創(chuàng)建ApplicationContext,然后加載具體的beans
- 若多個(gè)component對象共享bean蔓姚,可以把ApplicationContext做成static的捕虽,然后使用原子的方式保證只被初始化一次
component(spout/bolt)屬性的訪問范圍及線程安全
- 若component的屬性要被worker內(nèi)所有task共享,需要將這個(gè)變量定義為static
- 由于靜態(tài)屬性不會(huì)被序列化坡脐,因此不能在構(gòu)造函數(shù)初始化薯鳍,而是在spout#open/bolt#prepare來完成
- 另外,對static變量的訪問挨措,jstorm不負(fù)責(zé)線程同步及安全挖滤,需要用戶自行保證