Flink 基本合流操作
1、联合(Union)
最简单的合流操作,就是直接将多条流合在一起,叫作流的“联合”(union),如下图所示。联合操作要求必须流中的数据类型必须相同,合并之后的新流会包括所有流中的元素,数据类型不变。这种合流方式非常简单粗暴,就像公路上多个车道汇在一起一样
在代码中,只要基于DataStream直接调用.union()方法,传入其他DataStream作为参数,就可以实现流的联合了;得到的依然是一个DataStream:
stream1.union(stream2, stream3, ...)
注意:union()的参数可以是多个DataStream,所以联合操作可以实现多条流的合并。这里需要考虑一个问题。在事件时间语义下,水位线是时间的进度标志;不同的流中可能水位线的进展快慢完全不同,如果它们合并在一起,水位线又该以哪个为准呢?还以要考虑水位线的本质含义,是“之前的所有数据已经到齐了”;所以对于合流之后的水位线,也是要以最小的那个为准,这样才可以保证所有流都不会再传来之前的数据。换句话说,多流合并时处理的时效性是以最慢的那个流为准的。自然可以想到,这与之前介绍的并行任务水位线传递的规则是完全一致的;多条流的合并,某种意义上也可以看作是多个并行任务向同一个下游任务汇合的过程;
public static void main(String[] args) throws Exception { StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setParallelism(1); SingleOutputStreamOperator<Event> eventStream = env.socketTextStream("hadoop103", 9999) .map(data -> { String[] split = data.split(","); return new Event(split[0].trim(), split[1].trim(), Long.valueOf(split[2])); }) .assignTimestampsAndWatermarks(WatermarkStrategy. <Event>forBoundedOutOfOrderness(Duration.ofSeconds(2)) .withTimestampAssigner(new SerializableTimestampAssigner<Event>() { @Override public long extractTimestamp(Event element, long recordTimestamp) { return element.timestamp * 10000; } })); eventStream.print("eventStream "); SingleOutputStreamOperator<Event> eventStream1 = env.socketTextStream("hadoop103", 8888) .map(data -> { String[] split = data.split(","); return new Event(split[0].trim(), split[1].trim(), Long.valueOf(split[2])); }) .assignTimestampsAndWatermarks(WatermarkStrategy. <Event>forBoundedOutOfOrderness(Duration.ofSeconds(5)) .withTimestampAssigner(new SerializableTimestampAssigner<Event>() { @Override public long extractTimestamp(Event element, long recordTimestamp) { return element.timestamp * 10000; } })); eventStream1.print("eventStream1 "); /** * union 何以合并多个流,数据类型需要一样 */ eventStream.union(eventStream1).process(new ProcessFunction<Event, String>() { @Override public void processElement(Event value, Context ctx, Collector<String> out) throws Exception { out.collect("水位线 " + ctx.timerService().currentWatermark()); } }).print(); env.execute(); }
2、连接(Connect)