共計(jì) 2532 個(gè)字符,預(yù)計(jì)需要花費(fèi) 7 分鐘才能閱讀完成。
這篇文章主要介紹“component 的生命周期怎么理解”,在日常操作中,相信很多人在 component 的生命周期怎么理解問題上存在疑惑,丸趣 TV 小編查閱了各式資料,整理出簡單好用的操作方法,希望對(duì)大家解答”component 的生命周期怎么理解”的疑惑有所幫助!接下來,請(qǐng)跟著丸趣 TV 小編一起來學(xué)習(xí)吧!
storm 中的 spout,bolt 的生命周期,都是 storm 幫你管理好,你只要新建一個(gè)實(shí)例,指定該 component 的并行數(shù),就可以。那么 topology 中所用到的工具類的生命周期該如何處理,例如數(shù)據(jù)庫連接池、redis 的連接池,這些對(duì)象該放在哪里初始化?本文以 jdbc 連接池為例,討論此問題。閱讀本文前請(qǐng)先自行了解 storm topology 的運(yùn)行流程。
Storm Component 的生命周期
storm component 泛指 topoloty 中的 spout、bolt,是 spout 和 bolt 的一個(gè)統(tǒng)稱。而 component 生命周期,我結(jié)合 storm 作者 nathanmarz 大神的回答和自己的理解,描述一下:
1,當(dāng)提交了 topology 后,spout、bolt 的實(shí)例會(huì)在本地機(jī)器(執(zhí)行 storm submit 所在的機(jī)器)上被創(chuàng)建,并且在本地序列化。另外,所有的 component 的構(gòu)造函數(shù)、declareOutputFields 方法都本地會(huì)運(yùn)行一次。
2,整個(gè) topology 被上傳到 nimbus 上。
3,對(duì)應(yīng) supervisor 會(huì)向 nimbus 獲取序列化后的 topology 代碼,交給對(duì)應(yīng)的 worker 執(zhí)行。
4,每個(gè) worker 執(zhí)行如下:反序列化代碼,運(yùn)行對(duì)應(yīng) component 的 prepare/open(初始化對(duì)應(yīng)的 component)。舉個(gè)例子,某 spout 在 topology 中設(shè)置了 3 個(gè)并行度,且 topology 設(shè)置了 3 個(gè) worker,該 open 方法就會(huì)在 3 個(gè)不同的 worker 上分別調(diào)用 1 次,共調(diào)用 3 次。
5,worker 通知 executor 不斷循環(huán)去跑 nextTuple/execute 方法。
需要注意一點(diǎn):component 的初始化相關(guān)的操作應(yīng)放在 prepare/open 方法中執(zhí)行, 而不是在實(shí)例化 component 的時(shí)候進(jìn)行或者 topology 的 main 函數(shù)。
Jdbc Pool 初始化方案
參考 component 的生命周期,能想到有兩種方案:
1,每個(gè) component 都維持一個(gè)與數(shù)據(jù)庫的連接,此種方案適合于寫操作非常頻繁,component 數(shù)目比較少,且中間不會(huì)有一段時(shí)間沒有任何寫、讀操作,否則會(huì)發(fā)生 mysql connection timeout;另外可省去從連接池獲取連接,用完連接后返回給連接池這兩步操作。如果確定這種方案,則只要將數(shù)據(jù)庫的配置放到 config 中,在對(duì)應(yīng)的 component 中初始化數(shù)據(jù)庫連接即可。
2,在每 worker 中維持一個(gè)連接池,worker 中所有 executor 需要用到連接時(shí),從連接池中獲取,用后歸還。一般還是推薦這種方案。
下面說一下第二種方案的連接池,應(yīng)該在什么時(shí)候初始化。
首先明確一點(diǎn),在 topology 運(yùn)行中,一個(gè) worker 相當(dāng)于 jvm 進(jìn)程,相當(dāng)于有 N 個(gè) worker,就會(huì)有 N 個(gè)連接池。初始化連接池的動(dòng)作需要在 worker 端進(jìn)行,一個(gè) worker 中只有一個(gè)連接池的實(shí)例,適合用單例模式。
初始化思路:每個(gè) component 接收數(shù)據(jù)庫配置信息,在其 prepare/open 時(shí),初始化連接池,這里需要保證在單個(gè) worker 中只需要初始化一次就可以,即對(duì)初始化的代碼加鎖處理,保證只能有一個(gè) component 初始化。
在 storm 源碼包中,提供了 storm-jdbc 的實(shí)現(xiàn),其中用了 JDBC 連接池組件,具體實(shí)現(xiàn)思路就是上面討論的第二種方案。以下為初始化時(shí)加鎖的部分。
public class HikariCPConnectionProvider implements ConnectionProvider {
private Map String, Object configMap;
private transient HikariDataSource dataSource;
public HikariCPConnectionProvider(Map String, Object hikariCPConfigMap) {
this.configMap = hikariCPConfigMap;
}
@Override
public synchronized void prepare() { if(dataSource == null) { Properties properties = new Properties();
properties.putAll(configMap);
HikariConfig config = new HikariConfig(properties);
this.dataSource = new HikariDataSource(config);
this.dataSource.setAutoCommit(false);
}
}
@Override
public Connection getConnection() {
try { return this.dataSource.getConnection();
} catch (SQLException e) { throw new RuntimeException(e);
}
}
@Override
public void cleanup() { if(dataSource != null) { dataSource.shutdown();
}
}
}
看到,初始化 prepare 被上鎖了,以保證只初始化一次。其實(shí)這里可以再優(yōu)化一下:不要對(duì)方法加鎖,而是對(duì)具體初始化連接的代碼加鎖,減少鎖影響的范圍。
到此,關(guān)于“component 的生命周期怎么理解”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注丸趣 TV 網(wǎng)站,丸趣 TV 小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!