Fields和Tuple
概述
路径:storm-core/src/jvm/org/apache/storm/tuple/
Tuple和Fields是Storm用来传输数据(即流)的结构体。其中Tuple是Storm的数据传输单位,每一个tuple由一组数据组成。Tuple可以理解为由key-value组成的Map,不过,key会在发送发预先进行定义(即使用Fields来进行定义),Tuple只需要按序进行赋值即可,接收方在接收到Tuple后,根据下标来获取所需的值。以下是一个简单的例子。
@Override
public void declare OutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("from", "to", "duration"));
}
在上述的代码段中,使用new Fields(“from”, “to”, “duration”)来对组件所发送的Tuple的格式进行定义,即当向外发送Tuple时,tuple由三个字段组成。例如:
this.collector.emit(new Values(fromMobileNumber, toMobileNumber, duration))
对Tuple的各个字段进行赋值后向外发射。Values类用来实例化一个Tuple对象。
Fields
Fields数据结构用于存储(即前文提及的“定义”)Tuple的字段名列表。
public class Fields implements Iterable<String>, Serializable {
private static final long serialVersionUID = -3377931843059975424L;
//保存字段名
private List<String> _fields;
//保存从字段名到它在字段名列表中下标的映射
private Map<String, Integer> _index = new HashMap<>();
public Fields(String... fields) {
this(Arrays.asList(fields));
}
public Fields(List<String> fields) {
_fields = new ArrayList<>(fields.size());
for (String field : fields) {
if (_fields.contains(field))
throw new IllegalArgumentException(
String.format("duplicate field '%s'", field)
);
_fields.add(field);
}
index();
}
private void index() {
for(int i=0; i<_fields.size(); i++) {
_index.put(_fields.get(i), i);
}
}
...
}
Tuple
Tuple用来实现消息的传输,在Storm中,每一条消息都是一个Tuple对象。首先看Tuple接口的定义:
public interface Tuple extends ITuple{
//返回tuple对象的global stream id,即(component + stream)
@Deprecated
public GlobalStreamId getSourceGlobalStreamid();
public GlobalStreamId getSourceGlobalStreamId();
//返回发送这个Tuple的组件,即发送方
public String getSourceComponent();
//返回发送这个Tuple的Task Id
public int getSourceTask();
//返回tuple的StreamId,可以理解为流的标签或者分类
public String getSourceStreamId();
//返回消息序号,用于跟踪消息是否成功处理等
public MessageId getMessageId();
}
Tuple接口继承自ITuple,ITuple主要声明了一些对tuple对象的属性进行操作的函数,例如获取字段长度、取值等。
接下来看Tuple接口的实现类:
public class TupleImpl extends IndifferentAccessMap implements Seqable, Indexed, IMeta, Tuple {
//属性自上而下分别为消息的值、发送Task的Id、流Id、Topology信息、消息序号、(未知,来自coljure,待续)
private List<Object> values;
private int taskId;
private String streamId;
private GeneralTopologyContext context;
private MessageId id;
private IPersistentMap _meta;
public TupleImpl(GeneralTopologyContext context, List<Object> values, int taskId, String streamId, MessageId id) {
this.values = values;
this.taskId = taskId;
this.streamId = streamId;
this.id = id;
this.context = context;
String componentId = context.getComponentId(taskId);
Fields schema = context.getComponentOutputFields(componentId, streamId);
if(values.size()!=schema.size()) {
throw new IllegalArgumentException(
"Tuple created with wrong number of fields. " +
"Expected " + schema.size() + " fields but got " +
values.size() + " fields");
}
}
public TupleImpl(GeneralTopologyContext context, List<Object> values, int taskId, String streamId) {
this(context, values, taskId, streamId, MessageId.makeUnanchored());
}
...
}
TupleImpl实现类继承的类或者接口有一部分来自Coljure代码,其目的是为了能够在Coljure代码中更好地操作这些Tuple对象。
Values
用来快速地实例化一个Tuple对象。