Storm中的Task是最小的执行单位,与Worker,Executor分别对应于进程和线程不同,Task只是逻辑上的执行单位,它需要寄身与Executor中完成运行。一个Executor可以有多个Task,用户定义的Spout和Bolt对象都会被放置在Task上,当Executor收到属于某一个Task的消息时,就会调用与该Task对应的Spout或Bolt对象的相关方法进行处理。
TopologyContext对象那个为task对象的执行提供了上下文环境,它实际上给出了诸如Topology的结构,流的定义等于Topology相关的信息。
TopologyContext
topologyContext类继承自WorkerTopologyContext,它对应于某一个Task运行的上下文Bolt的prepare方法以及Spout的open方法均会传入该类的对象
public class TopologyContext extends WorkerTopologyContext implements IMetricsContext{}
public interface ITaskHook{}
public class BoltExecuteInfo{}
TopologyContext的父类GeneralTopologyContext
GeneralTopologyContext表示Topology的上下文环境,提供了较多的工具方法来方便获取Topology的结构信息
public class GeneraltopologyContext implements JSONAware {
private StormTopology _topology;Thrift生成的Storm Topology对象,含有Bolt和Spout的输入输出信息
private Map<Integer, String> _taskToComponent;为从taskId到组件Id的映射
private Map<String, List<Integer>> _componentToTasks;从组件id到其对应的task集合的映射
private Map<String, Map<String, Fields>> _componentToStreamToFields;从组件到每个输出流的模式的映射
private String _stormId;
private Map _stormConf;表示id和配置项
}
WorkerTopologyContext
继承自GeneralTopologyContext,是Storm中Worker运行的上下文环境,也是Executor中的共享环境
TopologyContext
在创建一个Task时,需要为其先创建一个TopologyContext对象,以便更加容易地获取Topology信息,mk-topology-context-builder函数用来创建该对象,
创建Task数据
mk-task-data函数用来创建与Task相关的数据,其参数为Executor的数据executor-data以及该task的taskid
send-unanchored
task使用send-unanchored函数来发送消息,该函数会利用tasks-fn函数来获得目标节点的taskid,然后调用Executor的:transfer-fn将消息发送到发送队列中,最终worker会利用zmq将消息发送给目标task,若目标task与当前task在同一个worker中,Worker则会将消息直接发送到该Task的接收队列中。
创建Task
mk-task函数用于创建一个新的Task,主要目标为通过调用mk-task-data函数为task创建对应的数据,该函数将用户定义的钩子函数注册到user-context数据中,同时向系统发送一条消息,SystemBolt
Storm中传输的消息以及序列化
Storm中实际传输的消息为:
SourceTaskId:int;StreamId:int;messageId:MessageId;TupleValues:List<Object>
反序列化的过程是:首先一次读取TaskId,并通过读取的流序列号查找映射表获取流名称,接下来调用MessageId反序列化方法读取MessageID信息,然后读取用户发送的消息。最后构建TupleImpl对象并返回,这里的流序号只用于消息的传输,其他地方看到的流序号实际上对应于这里的流名称。