Apache flink KeyedProcessFunction实现引发空指针异常?

Apache flink KeyedProcessFunction实现引发空指针异常?,apache-flink,flink-streaming,Apache Flink,Flink Streaming,第一个示例:来自“”的代码 我正在尝试重写KeyedProcessFunction类的processElement()。ProcessElement有3个参数,其中一个参数是上下文对象。当我试图从上下文对象检索时间戳时,它抛出空指针异常 在第一个示例代码中引发空指针异常的一行是 current.lastModified=ctx.timestamp() 第二个示例:“使用ApacheFlink进行流处理”一书的示例6.5 我在扩展KeyedProcessFunction类的类中声明了两个Value

第一个示例:来自“”的代码

我正在尝试重写KeyedProcessFunction类的processElement()。ProcessElement有3个参数,其中一个参数是上下文对象。当我试图从上下文对象检索时间戳时,它抛出空指针异常

在第一个示例代码中引发空指针异常的一行是

current.lastModified=ctx.timestamp()

第二个示例:“使用ApacheFlink进行流处理”一书的示例6.5

我在扩展KeyedProcessFunction类的类中声明了两个ValueState变量。当我试图检索状态中更新的最后一个值时,它返回空值

在第一个示例代码中引发空指针异常的一行是

Double prevTemp=lastTemp.value(); 如果(prevTemp==0.0 | | r.temperature 第一个示例代码

public class KeyedProcessFunctionExample {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment environment=
                StreamExecutionEnvironment.getExecutionEnvironment();

        environment.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);

        DataStream<Tuple2<String, String>> stream =
                environment.socketTextStream("localhost",9090)
                        .map(new MapFunction<String, Tuple2<String, String>>() {
                            @Override
                            public Tuple2<String, String> map(String s) throws Exception {
                                String[] words= s.split(",");

                                return new Tuple2<>(words[0],words[1]);
                            }
                        });

        DataStream<Tuple2<String, Long>> result = stream
                .keyBy(0)
                .process(new CountWithTimeoutFunction());

        result.print();

        environment.execute("Keyed Process Function Example");

    }
    public static class CountWithTimeoutFunction extends KeyedProcessFunction<Tuple, Tuple2<String, String>, Tuple2<String, Long>> {
        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) throws Exception {

            // retrieve the current count
            CountWithTimestamp current = state.value();
            if (current == null) {
                current = new CountWithTimestamp();
                current.key = value.f0;
            }

            // update the state's count
            current.count++;

            // set the state's timestamp to the record's assigned event time timestamp
            current.lastModified = ctx.timestamp();

            // write the state back
            state.update(current);

            // schedule the next timer 60 seconds from the current event time
            ctx.timerService().registerEventTimeTimer(current.lastModified + 60000);
        }

        @Override
        public void onTimer(
                long timestamp,
                OnTimerContext ctx,
                Collector<Tuple2<String, Long>> out) throws Exception {

            // get the state for the key that scheduled the timer
            CountWithTimestamp result = state.value();

            // check if this is an outdated timer or the latest timer
            if (timestamp == result.lastModified + 60000) {
                // emit the state on timeout
                out.collect(new Tuple2<String, Long>(result.key, result.count));
            }
        }
    }
}

class CountWithTimestamp {

    public String key;
    public long count;
    public long lastModified;
}
公共类KeyedProcessFunctionExample{
公共静态void main(字符串[]args)引发异常{
StreamExecutionEnvironment环境=
StreamExecutionEnvironment.getExecutionEnvironment();
环境.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
数据流=
socketTextStream(“localhost”,9090)
.map(新的映射函数(){
@凌驾
公共元组2映射(字符串s)引发异常{
String[]words=s.split(“,”);
返回新的元组2(单词[0],单词[1]);
}
});
数据流结果=数据流
.keyBy(0)
.process(新CountWithTimeoutFunction());
result.print();
执行(“键控流程功能示例”);
}
公共静态类CountWithTimeOut函数扩展了KeyedProcessFunction{
私人价值观国家;
@凌驾
公共void open(配置参数)引发异常{
state=getRuntimeContext().getState(新的ValueStateDescriptor(“myState”,CountWithTimestamp.class));
}
@凌驾
公共无效处理元素(
Tuple2值,
上下文ctx,
收集器输出)抛出异常{
//检索当前计数
CountWithTimestamp current=state.value();
如果(当前==null){
当前=新计数WithTimestamp();
current.key=value.f0;
}
//更新状态的计数
current.count++;
//将状态的时间戳设置为记录分配的事件时间戳
current.lastModified=ctx.timestamp();
//回信
状态更新(当前);
//从当前事件时间开始安排下一个计时器60秒
ctx.timerService().RegisterEventTimer(current.lastModified+60000);
}
@凌驾
即时公开作废(
长时间戳,
OnTimerContext ctx,
收集器输出)抛出异常{
//获取调度计时器的密钥的状态
CountWithTimestamp结果=state.value();
//检查这是过期的计时器还是最新的计时器
if(timestamp==result.lastModified+60000){
//发出超时状态
collect(新的Tuple2(result.key,result.count));
}
}
}
}
类CountWithTimestamp{
公共字符串密钥;
公众长时间计数;
公共长期服务;
}
第二个例子

public class KeyedProcessFunctionTimerExample {
    public static void main(String[] args) throws Exception{
        // set up the streaming execution environment
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        // use event time for the application
        env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime);

        DataStream<String> sensorData=
                env.addSource(new SensorSource())
                .keyBy(r -> r.id)
                .process(new TempIncreaseAlertFunction());

        sensorData.print();
        env.execute("Keyed Process Function execution");
    }

    public static class TempIncreaseAlertFunction extends KeyedProcessFunction<String, SensorReading, String> {

        private ValueState<Double> lastTemp;
        private ValueState<Long> currentTimer;

        @Override
        public void open(Configuration parameters) throws Exception {
            lastTemp = getRuntimeContext().getState(new ValueStateDescriptor<Double>("lastTemp", Types.DOUBLE));
            currentTimer = getRuntimeContext().getState(new ValueStateDescriptor<Long>("timer", org.apache.flink.api.common.typeinfo.Types.LONG));
        }

        @Override
        public void processElement(
                SensorReading r,
                Context ctx,
                Collector<String> out) throws Exception {

            // get previous Temp
            Double prevTemp = lastTemp.value();

            // update last temp
            lastTemp.update(r.temperature);

            Long curTimerTimestamp = currentTimer.value();

            if(prevTemp==0.0 || r.temperature < prevTemp) {
                ctx.timerService().deleteProcessingTimeTimer(curTimerTimestamp);
                currentTimer.clear();
            }
            else if(r.temperature > prevTemp && curTimerTimestamp == 0) {
                Long timerTs = ctx.timerService().currentProcessingTime() + 1000;
                ctx.timerService().registerProcessingTimeTimer(timerTs);
                currentTimer.update(timerTs);

            }
        }

        @Override
        public void onTimer(
                long ts,
                OnTimerContext ctx,
                Collector<String> out) throws Exception {

            out.collect("Temperature of sensor ' " + ctx.getCurrentKey() + " ' monotonically increased for 1 second.");
            currentTimer.clear();

        }
    }

}
公共类KeyedProcessFunctionTimerExample{
公共静态void main(字符串[]args)引发异常{
//设置流执行环境
StreamExecutionEnvironment env=StreamExecutionEnvironment.getExecutionEnvironment();
//为应用程序使用事件时间
环境setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime);
数据流传感器数据=
env.addSource(新的SensorSource())
.keyBy(r->r.id)
.process(新的TempIncreaseAlertFunction());
sensorData.print();
环境执行(“键控过程功能执行”);
}
公共静态类TempIncreaseAlertFunction扩展了KeyedProcessFunction{
私人财产;
私有值状态计时器;
@凌驾
公共void open(配置参数)引发异常{
lastTemp=getRuntimeContext().getState(新的ValueStateDescriptor(“lastTemp”,Types.DOUBLE));
currentTimer=getRuntimeContext().getState(新的ValueStateDescriptor(“timer”,org.apache.flink.api.common.typeinfo.Types.LONG));
}
@凌驾
公共无效处理元素(
传感器读数器,
上下文ctx,
收集器输出)抛出异常{
//获取以前的温度
Double prevTemp=lastTemp.value();
//更新最后的温度
最新温度更新(r温度);
Long curTimerTimestamp=currentTimer.value();
如果(prevTemp==0.0 | | r.温度prevTemp&&curTimerTimestamp==0){
长时间RTS=ctx.timerService().currentProcessingTime()+1000;
timerService().RegisterProcessingTimer(timerTs);
currentTimer.update(timerTs);
}
}
@凌驾
即时公开作废(
长ts,
OnTimerContext ctx,
收集器输出)抛出异常{
输出。收集传感器的温度