Flink DataStream Process Function

508 阅读1分钟

Process Function是Flink中low-level的方法。
在Process Function中可以获取到非常多的元数据信息,所以process function中可以非常的灵活处理数据。

Process Function中可以获取:

  • events: 数据流事件信息
  • state: Flink状态信息,通过RuntimeContext获取
  • Timer: 定时器信息,比如事件时间和处理时间等

process中的类需要实现KeyedProcessFunction和CoProcessFunction。

官方给的例子:
收集数据统计条数,并且当60秒内不再收到新的数据就触发窗口计算,输出统计结果

// 在process中实现KeyedProcessFunction
DataStream<Tuple2<String, Long>> result = stream
    .keyBy(value -> value.f0)
    .process(new CountWithTimeoutFunction());

//model
public class CountWithTimestamp {
    public String key;
    public long count;
    public long lastModified;
}
//自定义process function
public class CountWithTimeoutFunction 
        extends KeyedProcessFunction<Tuple, Tuple2<String, String>, Tuple2<String, Long>> {
    //记录状态 ValueState
    private ValueState<CountWithTimestamp> state;
    @Override
    public void open(Configuration parameters) throws Exception {
        //初始化状态
        state = getRuntimeContext().getState(new ValueStateDescriptor<>("myState", CountWithTimestamp.class));
    }
    @Override
    //处理每一条事件数据
    public void processElement(
            Tuple2<String, String> value,  //事件数据
            Context ctx,  //上下文
            Collector<Tuple2<String, Long>> out  //output收集器
            ) throws Exception {
        // 获取当前的计数
        CountWithTimestamp current = state.value();
        if (current == null) {
            current = new CountWithTimestamp();
            current.key = value.f0;
        }
        // 更新状态
        current.count++;
        current.lastModified = ctx.timestamp();
        state.update(current);
        // 重置计时器
        ctx.timerService().registerEventTimeTimer(current.lastModified + 60000);
    }
    @Override
    //计时器触发
    public void onTimer(
            long timestamp,   //当前timestamp
            OnTimerContext ctx,   //上下文
            Collector<Tuple2<String, Long>> out   //输出收集器
            ) throws Exception {
        // 获取当前状态
        CountWithTimestamp result = state.value();
        // 检查当前时间是不是状态时间的60秒之后
        if (timestamp == result.lastModified + 60000) {
            // 提交数据
            out.collect(new Tuple2<String, Long>(result.key, result.count));
        }
    }
}