JStorm使用问题

基本执行流程

以SequenceTopology为例,其加载流程为:

  • 用户提交拓扑的时候,会先将自己的代码打成jar包,通过nimbus提交拓扑到集群
  • nimbus执行jar时调用StormSubmitter.submitTopology,通过TopologyBuilder来创建拓扑的基本结构(即为spout和bolt创建了对象实例),并设置一些相关的conf
  • 接着将创建出来的拓扑对象进行序列化,通过nimbus调度再提交到各个机器上
  • 执行worker的时候,会再先将拓扑的相关对象反序列化并加载,然后执行

component(spout/bolt)序列化和反序列化

由于整个拓扑相关的对象都要被序列化,这意味着,component实现类必须是可序列化的,进一步意味着,spout/bolt的类属性也必须是可序列化的。除非:

  • spout/bolt的成员变量设置了transient/static,这样的变量将不会被序列化。
  • 属性值为null,未被初始化。

否则提交后可能会出现对象不可反序列化的异常。

component(spout/bolt)构造和执行顺序

  • component构造方法的执行时间,发生在创建对象的时候,即提交拓扑之前。
  • 若component构造方法初始化一些跟环境相关的变量(如连接DB),这时有可能是会有问题的。 因此,建议是放在spout.open/bolt.prepare方法中执行这些动作。
  • worker执行的时候,仅纯粹地执行对象反序列化,这时不会再调用构造函数。

spring场景下的初始化

  • 任何场景下,对环境相关的变量,都应该在spout.open/bolt.prepare中来初始化
  • 建议上述方法中创建ApplicationContext,然后加载具体的beans
  • 若多个component对象共享bean,可以把ApplicationContext做成static的,然后使用原子的方式保证只被初始化一次

component(spout/bolt)属性的访问范围及线程安全

  • 若component的属性要被worker内所有task共享,需要将这个变量定义为static
  • 由于静态属性不会被序列化,因此不能在构造函数初始化,而是在spout#open/bolt#prepare来完成
  • 另外,对static变量的访问,jstorm不负责线程同步及安全,需要用户自行保证

你可能感兴趣的:(JStorm使用问题)