flink1.12.x count window 数量滑动窗口(Sliding Windows)

说明

根据 key 分组后,相同 key 的数据,攒够一定数量时,就会触发计算,计算时,会算上 历史数据

最开始计算方式

key 分组后,相同 key 的数据,攒够 3 条,触发计算,如下图:

之后计算方式

key 分组后,相同 key 的数据,攒够3条,触发计算,并且 加上历史的 2 条,如下图:

案例

温度传感器发来 温度数据,由于发送数据太频繁,所以采用以下统计:

根据 传感器(id) 分组,相同传感器(id)的数据,每出现 3 次,统计该 传感器(id)的最大温度,并且算上历史的 2 条记录

发送数据格式:

{"id":"1","temp":35.3,"time":"2020-01-01 10:10:00"}

java

package countwindow;

import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.JsonNode;
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer;
import org.apache.kafka.clients.consumer.ConsumerConfig;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

public class SlidingWindow {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(2);

        // 定义kafka相关配置项
        Properties pro = new Properties();
        pro.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"hadoop1:9092,hadoop2:9092,hadoop3:9092");
        pro.setProperty(ConsumerConfig.GROUP_ID_CONFIG,"consumer-group");
        pro.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,"latest");
        // 内置连接器,创建FlinkKafka消费者,需要指定主题、反序列化、kafka配置
        FlinkKafkaConsumer<String> fkc = new FlinkKafkaConsumer("kafka2flink", new SimpleStringSchema(), pro);
        DataStreamSource<String> dss = env.addSource(fkc);

        SingleOutputStreamOperator<Tuple3<String, Double, Date>> max = dss
                .map(new MyMap())
                .keyBy(new KeySelector<Tuple3<String, Double, Date>, String>() {

                    @Override
                    public String getKey(Tuple3<String, Double, Date> value) throws Exception {
                        return value.f0;
                    }
                })
                .countWindow(5,3) 
                .max(1);// 根据索引是1的字段,取出最大值

        max.print();

        env.execute();
    }


    public static class MyMap implements MapFunction<String, Tuple3<String,Double,Date>>{
        @Override
        public Tuple3<String,Double,Date> map(String data) throws Exception {
            ObjectMapper om = new ObjectMapper();
            JsonNode jsonNode = om.readTree(data);
            JsonNode idJN = jsonNode.get("id");
            JsonNode tempJN = jsonNode.get("temp");
            JsonNode timeJN = jsonNode.get("time");

            String id = null;
            Double temp = null;
            Date time = null;

            if(idJN!=null){
                id = idJN.asText();
            }
            if(tempJN!=null){
                temp = tempJN.asDouble();
            }
            if(timeJN!=null){
                String timeStr = timeJN.asText();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                time = sdf.parse(timeStr);
            }
            return Tuple3.of(id,temp,time);
        }
    }
}

启动zk

登录 hadoop1,执行下面命令:

/program/bin/zk.sh start

启动kafka

登录 hadoop1,执行下面命令:

/program/bin/kafka.sh start

在 idea 中运行 flink 程序

创建生产者、指定主题

登录 hadoop1,执行下面命令:

/program/kafka_2.12-2.4.1/bin/kafka-console-producer.sh --broker-list hadoop1:9092,hadoop2:9092,hadoop3:9092 --topic kafka2flink

发送数据

{"id":"1","temp":35.3,"time":"2020-01-01 10:10:00"}
{"id":"1","temp":33.1,"time":"2020-01-01 10:12:00"}
{"id":"1","temp":22.5,"time":"2020-01-01 10:14:00"}

由于 id 是 1 的数据 攒够 3 条,所以 触发统计,执行结果:

1> (1,35.3,Wed Jan 01 10:10:00 CST 2020)

继续发送数据

{"id":"1","temp":22.5,"time":"2020-01-01 10:14:00"}
{"id":"1","temp":22.5,"time":"2020-01-01 10:14:00"}
{"id":"1","temp":22.5,"time":"2020-01-01 10:14:00"}

由于 id 是 1 的数据 攒够 3 条,所以 触发统计,但会 算上 历史的 2 条数据,即:总共 5 条数据,执行结果:

1> (1,33.1,Wed Jan 01 10:12:00 CST 2020)

原文出处:/show_1IX471MT1bF5.html