Flink 系例 之 KeyedProcessFunction

KeyedProcessFunction 方法:是一个基于 KeyedStream 流处理方法,可以灵活的对每个输入 KeyedStream 进行逻辑处理,并支持定时器时间事件

示例环境

java.version: 1.8.x
flink.version: 1.11.1

示例数据源 (项目码云下载)

Flink 系例 之 搭建开发环境与数据

KeyedProcess.java

import com.flink.examples.DataSource;
import com.google.gson.Gson;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.flink.api.common.state.ValueState;
import org.apache.flink.api.common.state.ValueStateDescriptor;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.TimeCharacteristic;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.KeyedProcessFunction;
import org.apache.flink.util.Collector;

import java.util.Date;
import java.util.List;

/**
 * @Description KeyedProcessFunction方法:是一个基于KeyedStream流处理方法,可以灵活的对每个输入KeyedStream进行逻辑处理,并支持定时器时间事件
 */
public class KeyedProcess {

    /**
     * 遍历集合,分别打印不同性别的信息,对于执行超时,自动触发定时器
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        //使用event time,需要指定事件的时间戳
        env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
        env.setParallelism(1);
        List<Tuple3<String, String, Integer>> tuple3List = DataSource.getTuple3ToList();
        DataStream<String> dataStream = env.fromCollection(tuple3List)
                .keyBy((KeySelector<Tuple3<String, String, Integer>, String>) k -> k.f1)
                //处理每keyBy后的每一个数据流,process方法通常应用于KeyedStream类型的数据流处理
                .process(new KeyedProcessFunction<String, Tuple3<String, String, Integer>, String>() {
                    //可以缓存同一个keyBy下的上下文状态
                    private ValueState<String> name ;
                    @Override
                    public void open(Configuration parameters) throws Exception {
                        super.open(parameters);
                        //初始化自定义上下文,并指定类型为String
                        name = getRuntimeContext().getState(new ValueStateDescriptor<String>("name", String.class));
                    }
                    /**
                     *  处理每一个输入的数据流
                     *   ProcessFunction 可以被认为是一种提供了对 KeyedState 和定时器访问的 FlatMapFunction。
                     *   每在输入流中接收到一个事件,就会调用来此函数来处理。
                     *   对于容错的状态,ProcessFunction 可以通过 RuntimeContext 访问 KeyedState,类似于其他有状态函数访问 KeyedState。
                     * @param value     数据流对象
                     * @param ctx       上下文信息
                     * @param out       输出结果的集合
                     * @throws Exception
                     */
                    @Override
                    public void processElement(Tuple3<String, String, Integer> value, Context ctx, Collector<String> out) throws Exception {
                        //模拟超时,如果王五,则暂停5s
                        if (value.f0.equals("王五")){
                            name.update(value.f0);
                            //注册ProcessingTime处理时间的定时器,当时间达到指定值时触发onTimer事件,如:当前元素因3s内处理完毕,超时则触发onTimer方法
                            ctx.timerService().registerProcessingTimeTimer(System.currentTimeMillis() + (3 * 1000));
                            //模拟5s超时
                            Thread.sleep(5 * 1000);
                        }
                        out.collect(new Gson().toJson(value));
                    }
                    /**
                     * 注册的定时器触发时调用
                     *  Timers 定时器可以对处理时间和事件时间的变化做一些处理。
                     *  每次调用 processElement() 都可以获得一个 Context 对象,通过该对象可以访问元素的事件时间戳以及 TimerService。
                     *  TimerService 可以为尚未发生的事件时间/处理时间实注册回调。
                     *  当定时器到达某个时刻时,会调用 onTimer() 方法。
                     *  在调用期间,所有状态再次限定为定时器创建的键,允许定时器操作 KeyedState。
                     * @param timestamp 定时器所设定的触发的时间戳
                     * @param ctx       上下文信息
                     * @param out       输出结果的集合
                     * @throws Exception
                     */
                    @Override
                    public void onTimer(long timestamp, OnTimerContext ctx, Collector<String> out) throws Exception {
                        super.onTimer(timestamp, ctx, out);
                        String timeStr = DateFormatUtils.format(new Date(timestamp), "yyyy-MM-dd HH:mm:ss");
                        out.collect(ctx.getCurrentKey() + ",用户:"+ name.value() + ",当前任务处理超时:" + timeStr);
                        //删除定时器触发时间
                        ctx.timerService().deleteProcessingTimeTimer(timestamp);
                        name.update(null);
                    }
                });
        dataStream.print();
        env.execute("flink Filter job");
    }
}

打印结果

{"f0":"张三","f1":"man","f2":20}
{"f0":"李四","f1":"girl","f2":24}
{"f0":"王五","f1":"man","f2":29}
man,用户:王五,当前任务处理超时:2020-09-16 11:17:15
{"f0":"刘六","f1":"girl","f2":32}
{"f0":"伍七","f1":"girl","f2":18}
{"f0":"吴八","f1":"man","f2":30}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值