Stream.stateQuery(TridentState state, Fields inputFields, QueryFunction function, Fields functionFields)方法主要是根据输入从持久化存储系统中读取相应的数据并将其当作一个数据流供Strom Topology使用。下面我们看一下stateQuery的具体执行过程:
@Override
public void startBatch(ProcessorContext processorContext) {
processorContext.state[_context.getStateIndex()] = new BatchState();
}
在Storm框架进行一个batch处理的时候,会调用startBatch方法,生成该batch内部使用的BatchState实例。
@Override
public void execute(ProcessorContext processorContext, String streamId, TridentTuple tuple) {
BatchState state = (BatchState) processorContext.state[_context.getStateIndex()];
state.tuples.add(tuple);
state.args.add(_projection.create(tuple));
}
对于batch中的每一个tuple,Strom框架会进行两种操作,一是将原始的tuple存储到BatchState中;一是将原始的tuple进行“投影”操作,将tuple中需要的列进行组成一个新的tuple进行存储。
@Override
public void finishBatch(ProcessorContext processorContext) {
BatchState state = (BatchState) processorContext.state[_context.getStateIndex()];
if(!state.tuples.isEmpty()) {
List<Object> results = _function.batchRetrieve(_state, Collections.unmodifiableList(state.args));
if(results.size()!=state.tuples.size()) {
throw new RuntimeException("Results size is different than argument size: " + results.size() + " vs " + state.tuples.size());
}
for(int i=0; i<state.tuples.size(); i++) {
TridentTuple tuple = state.tuples.get(i);
Object result = results.get(i);
_collector.setContext(processorContext, tuple);
_function.execute(state.args.get(i), result, _collector);
}
}
}
当一个batch的都有tuple都处理完成后,strom框架调用finishBatch函数。该函数主要调用QueryFunction函数。该函数有两个参数,即BatchState以及execute函数中生成的新tuple。对于每一个获取的结果,通过调用QueryFunction的execute方法来完成最终的处理。
public interface QueryFunction<S extends State, T> extends EachOperation {
List<T> batchRetrieve(S state, List<TridentTuple> args);
void execute(TridentTuple tuple, T result, TridentCollector collector);
}