您好,登录后才能下订单哦!
这篇文章主要介绍“component的生命周期怎么理解”,在日常操作中,相信很多人在component的生命周期怎么理解问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”component的生命周期怎么理解”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
storm中的spout,bolt的生命周期,都是storm帮你管理好,你只要新建一个实例,指定该component的并行数,就可以。那么topology中所用到的工具类的生命周期该如何处理,例如数据库连接池、redis的连接池,这些对象该放在哪里初始化?本文以jdbc连接池为例,讨论此问题。阅读本文前请先自行了解storm topology的运行流程。
Storm Component的生命周期
storm component泛指topoloty中的spout、bolt,是spout和bolt的一个统称。而component生命周期,我结合storm作者nathanmarz大神的回答和自己的理解,描述一下:
1,当提交了topology后,spout、bolt的实例会在本地机器(执行storm submit所在的机器)上被创建,并且在本地序列化。另外,所有的component的构造函数、declareOutputFields方法都本地会运行一次。
2,整个topology被上传到nimbus上。
3,对应supervisor会向nimbus获取序列化后的topology代码,交给对应的worker执行。
4,每个worker执行如下:反序列化代码,运行对应component的prepare/open(初始化对应的component)。举个例子,某spout在topology中设置了3个并行度,且topology设置了3个worker,该open方法就会在3个不同的worker上分别调用1次,共调用3次。
5,worker通知executor不断循环去跑nextTuple/execute方法。
需要注意一点:component的初始化相关的操作应放在prepare/open方法中执行, 而不是在实例化component的时候进行或者topology的main函数。
Jdbc Pool 初始化方案
参考component的生命周期,能想到有两种方案:
1,每个component都维持一个与数据库的连接,此种方案适合于写操作非常频繁,component数目比较少,且中间不会有一段时间没有任何写、读操作,否则会发生mysql connection timeout;另外可省去从连接池获取连接,用完连接后返回给连接池这两步操作。如果确定这种方案,则只要将数据库的配置放到config中,在对应的component中初始化数据库连接即可。
2,在每worker中维持一个连接池,worker中所有executor需要用到连接时,从连接池中获取,用后归还。一般还是推荐这种方案。
下面说一下第二种方案的连接池,应该在什么时候初始化。
首先明确一点,在topology运行中,一个worker相当于jvm进程,相当于有N个worker,就会有N个连接池。初始化连接池的动作需要在worker端进行,一个worker中只有一个连接池的实例,适合用单例模式。
初始化思路:每个component接收数据库配置信息,在其prepare/open时,初始化连接池,这里需要保证在单个worker中只需要初始化一次就可以,即对初始化的代码加锁处理,保证只能有一个component初始化。
在storm源码包中,提供了storm-jdbc的实现,其中用了JDBC 连接池组件,具体实现思路就是上面讨论的第二种方案。以下为初始化时加锁的部分。
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被上锁了,以保证只初始化一次。其实这里可以再优化一下:不要对方法加锁,而是对具体初始化连接的代码加锁,减少锁影响的范围。
到此,关于“component的生命周期怎么理解”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。