在 Flink 的数据流中,所有元素均继承自 StreamElement
抽象类。该抽象类有 6 个子类,即 Flink 的数据流中有且仅有这 6 种类型的元素。
继承关系如下图:
StreamRecord<T>
:数据流中的存储数据的元素,包含一个T
类型的值和一个可选择的时间戳。Watermark
:数据流中的 WatermarkWatermarkStatus
:数据流状态标记,包含WatermarkStatus#IDLE
和WatermarkStatus#ACTIVE
两种,用于标记数据流的空闲状态,告知下游算子是否需要等待这个数据流后续的 WatermarkLatencyMarker
:延迟标记,用于端到端延迟追踪的指标统计,详见 《Flink 官方文档:Operations - 指标 - End-to-End latency tracking》RecordAttributes
:记录属性信息,提供用于优化作业的信息EndOfDataMarker
:数据流结束标记
1 StreamElement
:数据流对象的抽象类(内部 API)
在 StreamElement
抽象类中,仅实现了检查实例是否为 5 种子类,以及将实例强转为 5 种子类的对象的方法,没有实现具体的方法。
源码|Github|org.apache.flink.streaming.runtime.streamrecord.StreamElement
@Internal
public abstract class StreamElement {
public final boolean isWatermark() { return getClass() == Watermark.class; }
public final boolean isWatermarkStatus() { return getClass() == WatermarkStatus.class; }
public final boolean isRecord() { return getClass() == StreamRecord.class; }
public final boolean isLatencyMarker() { return getClass() == LatencyMarker.class; }
public final boolean isRecordAttributes() { return getClass() == RecordAttributes.class; }
@SuppressWarnings("unchecked")
public final <E> StreamRecord<E> asRecord() { return (StreamRecord<E>) this; }
public final Watermark asWatermark() { return (Watermark) this; }
public final WatermarkStatus asWatermarkStatus() { return (WatermarkStatus) this; }
public final LatencyMarker asLatencyMarker() { return (LatencyMarker) this; }
public final RecordAttributes asRecordAttributes() { return (RecordAttributes) this; }
}
2 StreamRecord<T>
:数据流中的记录(内部 API)
在 StreamRecord
的对象属性中,包含一个 T
类型的值 value
和一个可供选择的 long
类型的 timestamp
,以及标记该 timestamp
是否为空的布尔值 hasTimestamp
。
StreamRecord
有 2 个构造方法,一个是仅提供 T value
的构造方法,一个是提供 T value
和时间戳 timestamp
的构造方法。此外,提供了获取和更新 value
和 timestamp
的方法。
源码|Github|org.apache.flink.streaming.runtime.streamrecord.StreamRecord
(部分)
@Internal
public final class StreamRecord<T> extends StreamElement {
private T value;
private long timestamp;
private boolean hasTimestamp;
public StreamRecord(T value) {
this.value = value;
}
public StreamRecord(T value, long timestamp) {
this.value = value;
this.timestamp = timestamp;
this.hasTimestamp = true;
}
public T getValue() { return value; }
public long getTimestamp() {
if (hasTimestamp) {
return timestamp;
} else {
return Long.MIN_VALUE;
}
}
public boolean hasTimestamp() { return hasTimestamp; }
@SuppressWarnings("unchecked")
public <X> StreamRecord<X> replace(X element) {
this.value = (T) element;
return (StreamRecord<X>) this;
}
@SuppressWarnings("unchecked")
public <X> StreamRecord<X> replace(X value, long timestamp) {
this.timestamp = timestamp;
this.value = (T) value;
this.hasTimestamp = true;
return (StreamRecord<X>) this;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
this.hasTimestamp = true;
}
public void eraseTimestamp() {
this.hasTimestamp = false;
}
}
3 Watermark
在 Watermark
的对象属性中,只有一个 Watermark 标记的时间戳,与设置 Watermark 策略时的 org.apache.flink.api.common.eventtime.Watermark
一致,这个时间戳在构造方法中传入后即不可变。
源码|Github|org.apache.flink.api.common.eventtime.Watermark
(部分)
@PublicEvolving
public final class Watermark extends StreamElement {
private final long timestamp;
public Watermark(long timestamp) {
this.timestamp = timestamp;
}
public long getTimestamp() {
return timestamp;
}
}
4 WatermarkStatus
:数据流状态(内部 API)
WatermarkStatus
用于标记数据流的空闲状态,避免空闲数据源影响下游算子的 Watermark 更新,具体介绍详见 “2.6 空闲数据源的处理”。而上游算子向下游算子通知数据流的空闲状态,则是通过发出 WatermarkStatus#IDLE
和 WatermarkStatus#ACTIVE
来实现的。
源码|Github|org.apache.flink.streaming.runtime.watermarkstatus.WatermarkStatus
@Internal
public final class WatermarkStatus extends StreamElement {
public static final int IDLE_STATUS = -1;
public static final int ACTIVE_STATUS = 0;
public static final WatermarkStatus IDLE = new WatermarkStatus(IDLE_STATUS);
public static final WatermarkStatus ACTIVE = new WatermarkStatus(ACTIVE_STATUS);
public final int status;
public WatermarkStatus(int status) {
if (status != IDLE_STATUS && status != ACTIVE_STATUS) {
throw new IllegalArgumentException(
"Invalid status value for WatermarkStatus; "
+ "allowed values are "
+ ACTIVE_STATUS
+ " (for ACTIVE) and "
+ IDLE_STATUS
+ " (for IDLE).");
}
this.status = status;
}
public boolean isIdle() {
return this.status == IDLE_STATUS;
}
public boolean isActive() {
return !isIdle();
}
public int getStatus() {
return status;
}
}
在实现上,通过类似枚举类的方式,使用静态常量 IDLE
和 ACTIVE
表示空闲状态和活跃状态的 WatermarkStatus
的对象。此外,提供了 isIdle()
方法和 isActive()
方法用于查询当前对象是标记空闲状态还是活跃状态。