开发Flink作业过程需要用到的一些常用接口:
一、创建StreamExecutionEnvironment
StreamExecutionEnvironment主要用来配置一些运行参数以及创建Source。
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
配置开启Checkpoint(方便作业失败后自动恢复):
env.enableCheckpointing(60000);
CheckpointConfig config = env.getCheckpointConfig();
config.enableExternalizedCheckpoints(ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);
二、创建Source
Source即待处理的数据的来源,一般是外部系统,比如HDFS、Kafka等;Flink提供丰富的扩展来支持不同的Source,我们以Kafka为例:
FlinkKafkaConsumer<String> consumer = new FlinkKafkaConsumer[String](topic, new SimpleStringSchema(), props);
DataStreamSource<String> kafkaSource = env.addSource(consumer);
三、转换操作(Transformation)
详细说明请查阅官方文档,我们只列一些常用的转换操作。
1.Map
DataStream → DataStream,输入一个数据产生一个数据;
DataStream<Integer> dataStream = //...
dataStream.map(new MapFunction<Integer, Integer>() {
@Override
public Integer map(Integer value) throws Exception {
return 2 * value;
}
});
注意,对于Scala Option,Scala Case Class和Java/Scala Tuple类型,map的返回值不能是null;
- Option类型可以返回None;
- Case Class和Tuple,可以设置变量为null,比如new Tuple2(null, null);
2.FlatMap
DataStream → DataStream ,输入一个数据,产生0个、1个或者多个输出;
dataStream.flatMap(new FlatMapFunction<String, String>() {
@Override
public void flatMap(String value, Collector<String> out)
throws Exception {
for(String word: value.split(" ")){
out.collect(word);
}
}
});
3.Filter
DataStream → DataStream,计算每个数据的布尔值,并返回布尔值为true的数据;
dataStream.filter(new FilterFunction<Integer>() {
@Override
public boolean filter(Integer value) throws Exception {
return value != 0;
}
});
4.KeyBy
DataStream → KeyedStream,逻辑地将一个流拆分成不相交的分区,每个分区包含具有相同Key的元素. 在内部是以hash的形式实现的。 注意,以下两种类型不能作为Key:
- POJO类型但是没有重写
hashCode方法; - 数组类型;
dataStream.keyBy("someKey") // 如果dataStream的数据类型为POJO,可以通过这种方式,直接指定POJO的某个字段;
dataStream.keyBy(0) // 如果dataStream的数据类型为Tuple,可以通过这种方式指定第几个元素作为key;
// 如果是其他类型,可以使用KeySelector,推荐这种方式;
public class WC {public String word; public int count;}
DataStream<WC> words = // [...]
KeyedStream<WC> keyed = words
.keyBy(new KeySelector<WC, String>() {
public String getKey(WC wc) { return wc.word; }
});
关于Flink中POJO的说明:
Flink对于POJO的认定有一定的规则,只有满足下面全部条件,一个类型才能被认定为POJO(才可以使用"变量名"来引用成员变量,比如dataStream.keyBy("someKey")):
- 这个类必须是public的并且不是内嵌类;
- 必须有一个pulic的无参数构造函数;
- 对于所有的非static、非transient的成员变量,要不它是public且非final的,要不它有符合Java Bean规范的set和get方法;
5.Reduce
KeyedStream → DataStream,一个分组数据流的"滚动"规约操作. 合并当前的元素和上次规约的结果,产生一个新的值.
keyedStream.reduce(new ReduceFunction<Integer>() {
@Override
public Integer reduce(Integer value1, Integer value2)
throws Exception {
return value1 + value2;
}
});
6.Window
KeyedStream → WindowedStream,Windows 是在一个分区的 KeyedStreams中定义的. Windows 根据某些特性将每个key的数据进行分组 (例如:在5秒内到达的数据)
dataStream
.keyBy(0)
.window(TumblingEventTimeWindows.of(Time.seconds(5))); // Last 5 seconds of data
7.Window Reduce
在WindowedStream执行reduce操作;
windowedStream
.reduce(new ReduceFunction<Tuple2<String,Integer>>() {
public Tuple2<String, Integer> reduce(Tuple2<String, Integer> value1, Tuple2<String, Integer> value2) throws Exception {
return new Tuple2<String,Integer>(value1.f0, value1.f1 + value2.f1);
}
});
四、创建Sink
数据处理完成后,一般需要输出到外部系统保存,比如HDFS、kafka等;我们还是以kafka为例:
FlinkKafkaProducer<String> talosProducer = new FlinkKafkaProducer[String](KAFKA_SERVER, topic, new SimpleStringSchema());
dataStream.addSink(talosProducer);
五、启动程序
一切就绪,启动程序。
env.execute("flink-quickstart");
注意: 不要catch上面方法抛出的Throwable异常! (这是因为正常情况下env.execute会抛出一个Error,这是Flink的内部逻辑需要)
// 错误示范
try {
streamEnv.execute("flink-talos-quickstart");
} catch (Throwable e) {
logger.error(xxxx);
}
941

被折叠的 条评论
为什么被折叠?



