本文原创,转载请注明出处:
使用KafkaSpout需要子类实现Scheme,storm-kafka实现了StringScheme,KeyValueStringScheme等等,大家可以用。
这些Scheme主要负责从消息流中解析出所需要的数据。
public interface Scheme extends Serializable {
public List<Object> deserialize(byte[] ser);
public Fields getOutputFields();
}
需要实现反序列化方法和输出fields名称,来看简单StringScheme实现:
public class StringScheme implements Scheme {
public static final String STRING_SCHEME_KEY = "str";
public List<Object> deserialize(byte[] bytes) {
return new Values(deserializeString(bytes));
}
public static String deserializeString(byte[] string) {
try {
return new String(string, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public Fields getOutputFields() {
return new Fields(STRING_SCHEME_KEY);
}
}
其实就是直接返回了一个String,在Spout往后发射时就一个字段,其名为“str”,如果采用StringScheme时,大家在Bolt中可以用
tuple.getStringByField("str")
来获取其值。有人有疑问前面为什么用new SchemeAsMultiScheme(new StringScheme())呐?来看SchemeAsMultiScheme代码
public class SchemeAsMultiScheme implements MultiScheme {
public final Scheme scheme;
public SchemeAsMultiScheme(Scheme scheme) {
this.scheme = scheme;
}
@Override public Iterable<List<Object>> deserialize(final byte[] ser) {
List<Object> o = scheme.deserialize(ser);
if(o == null) return null;
else return Arrays.asList(o);
}
@Override public Fields getOutputFields() {
return scheme.getOutputFields();
}
}
public interface MultiScheme extends Serializable {
public Iterable<List<Object>> deserialize(byte[] ser);
public Fields getOutputFields();
}
其实本身还是调用了传入的scheme方法,只不过返回结果组合成一个list而已,小弟觉得不用也可以。但是storm-kafka里面默认是需要的,在KafkaUtils解析message时调用scheme信息:
public static Iterable<List<Object>> generateTuples(KafkaConfig kafkaConfig, Message msg) {
Iterable<List<Object>> tups;
ByteBuffer payload = msg.payload();
if (payload == null) {
return null;
}
ByteBuffer key &#