Flink是什么?如何简单应用?

Flink是什么?

Flink介绍

Apache Flink是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算。Flink设计为在所有常见的集群环境中运行,以内存速度和任何规模执行计算。
在这里,我们解释了Flink架构的重要方面。

处理无界和有界数据

任何类型的数据都是作为事件流产生的。信用卡交易,传感器测量,机器日志或网站或移动应用程序上的用户交互,所有这些数据都作为流生成。 数据可以作为无界或有界流处理。

无界流有一个开始但没有定义的结束。它们不会在生成时终止并提供数据。必须持续处理无界流,即必须在摄取事件后立即处理事件。无法等待所有输入数据到达,因为输入是无界的,并且在任何时间点都不会完成。处理无界数据通常要求以特定顺序(例如事件发生的顺序)摄取事件,以便能够推断结果完整性。
有界流具有定义的开始和结束。可以在执行任何计算之前通过摄取所有数据来处理有界流。处理有界流不需要有序摄取,因为可以始终对有界数据集进行排序。有界流的处理也称为批处理。
Apache Flink擅长处理无界和有界数据集。精确控制时间和状态使Flink的运行时能够在无界流上运行任何类型的应用程序。有界流由算法和数据结构内部处理,这些算法和数据结构专门针对固定大小的数据集而设计,从而产生出色的性能。

部署应用程序在任何地方

Apache Flink是一个分布式系统,需要计算资源来执行应用程序。Flink集成了所有常见的集群资源管理器,如Hadoop YARN、Apache Mesos和Kubernetes,但也可以设置为作为独立集群运行。

Flink被设计成能够很好地工作于前面列出的每个资源管理器。这是通过特定于资源管理器的部署模式实现的,这种部署模式允许Flink以其惯用的方式与每个资源管理器交互。

在部署Flink应用程序时,Flink根据应用程序的配置并行性自动识别所需的资源,并从资源管理器请求它们。如果发生故障,Flink将通过请求新的资源来替换失败的容器。提交或控制应用程序的所有通信都是通过REST调用进行的。这简化了Flink在许多环境中的集成。

以任何规模运行应用程序

Flink设计用于在任何规模上运行有状态流应用程序。应用程序被并行化成数千个任务,这些任务分布在一个集群中并发执行。因此,应用程序实际上可以利用无限数量的cpu、主内存、磁盘和网络IO。此外,Flink很容易保持非常大的应用状态。它的异步和增量检查点算法确保了对处理延迟的最小影响,同时保证了精确的一次状态一致性。

利用内存中的性能

有状态Flink应用程序针对本地状态访问进行了优化。任务状态总是在内存中维护,如果状态大小超过可用内存,则在具有访问效率的磁盘数据结构中维护。因此,任务通过访问本地(通常是在内存中)状态来执行所有计算,从而产生非常低的处理延迟。Flink通过定期和异步检查本地状态到持久存储,保证了在发生故障时的精确一次状态一致性。

Flink Demo展示

利用maven导入依赖

 <dependency>
      <groupId>org.apache.flink</groupId>
      <artifactId>flink-java</artifactId>
      <version>1.10.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.flink</groupId>
      <artifactId>flink-streaming-java_2.11</artifactId>
      <version>1.10.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.flink</groupId>
      <artifactId>flink-connector-kafka-0.11_2.11</artifactId>
      <version>1.10.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.flink</groupId>
      <artifactId>flink-statebackend-rocksdb_2.11</artifactId>
      <version>1.10.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.flink</groupId>
      <artifactId>flink-table-planner_2.11</artifactId>
      <version>1.10.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.flink</groupId>
      <artifactId>flink-table-planner-blink_2.11</artifactId>
      <version>1.10.1</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.38</version>
    </dependency>
    <dependency>
      <groupId>org.apache.bahir</groupId>
      <artifactId>flink-connector-redis_2.11</artifactId>
      <version>1.0</version>
    </dependency>
    <!-- scala -->
    <dependency>
      <groupId>org.apache.flink</groupId>
      <artifactId>flink-scala_2.11</artifactId>
      <version>1.10.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.flink</groupId>
      <artifactId>flink-streaming-scala_2.11</artifactId>
      <version>1.10.1</version>
    </dependency>

利用Scala 进行wordcount

代码如下:

object WordCount {
  def main(args: Array[String]): Unit = {
    // 1、创建流处理的执行环境
    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)   //并行度

    // 2、source 接受socket 数据流
    val inputDataStream: DataStream[String] = env.socketTextStream("192.168.146.222",7777)

    // 3、转换操作
    val resultDataStream: DataStream[(String, Int)] = inputDataStream
      .flatMap(_.split("\\s+"))
      .map(x => (x, 1))
      .keyBy((0))
      .sum(1)

    // 4、sink
    resultDataStream.print()

    env.execute("wordcount")
  }
}

虚拟机利用nc 模拟输入流,运行如下:
在这里插入图片描述

利用Java进行wordcount

代码如下:

public class WordCount{
    public static void main(String[] args) throws Exception {
        // 1、定义env执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(3);

        // 2、source
        DataStreamSource<String> inputDataStream = env.socketTextStream("192.168.146.222", 7777);

        // 3、数据转换
        SingleOutputStreamOperator<Tuple2<String, Integer>> result = inputDataStream.flatMap(new MyFlatMapper())
                .keyBy(0)
                .sum(1);

        //sink
        result.print("wordcount");

        env.execute("java word count");
    }

    public static class MyFlatMapper implements FlatMapFunction<String, Tuple2<String,Integer>> {
        @Override
        public void flatMap(String s, Collector<Tuple2<String,Integer>> collector) throws Exception {
            String[] words = s.split("\\s+");
            for (String word : words) {
                collector.collect(new Tuple2<String, Integer>(word,1));
            }
        }
    }
}

同样利用nc进行模拟输入流,运行如图所示:
在这里插入图片描述

利用Java进行wordcount2

此demo利用批处理wordcount,区别于上一个demo的流处理,批处理采用一次性将数据处理完毕,处理结束该程序就结束了,并不像流处理会一直运行等待数据传入。
代码如下:

public class WordCount2 {
    public static void main(String[] args) throws Exception {
        // 1、定义env执行环境
//        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//        env.setParallelism(3);
        ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();

        String filePath="E:\\ideaProjects\\flinkstu\\resource\\words.txt";
        DataSource<String> stringDataSource = env.readTextFile(filePath);
        AggregateOperator<Tuple2<String, Integer>> result = stringDataSource.flatMap(new WordCount.MyFlatMapper())
                .groupBy(0)
                .sum(1);
        result.print();


//        env.execute("java word count1");   批处理不需要执行此步骤
    }

    private static class MyFlatMapper implements FlatMapFunction<String, Tuple2<String,Integer>> {
        @Override
        public void flatMap(String s, Collector<Tuple2<String,Integer>> collector) throws Exception {
            String[] words = s.split("\\s+");
            for (String word : words) {
                collector.collect(new Tuple2<String, Integer>(word,1));
            }
        }
    }
}

运行如图所示:
在这里插入图片描述

Source 展示

数据接收

source1_Collect

直接进行数据展示
先创建样例类:

public class SensorReading {
    private String id;
    private Long timestamp;
    private Double temperature;

    @Override
    public String toString() {
        return "SensorReading{" +
                "id='" + id + '\'' +
                ", timestamp=" + timestamp +
                ", temperature=" + temperature +
                '}';
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(Long timestamp) {
        this.timestamp = timestamp;
    }

    public Double getTemperature() {
        return temperature;
    }

    public void setTemperature(Double temperature) {
        this.temperature = temperature;
    }

    public SensorReading() {
    }

    public SensorReading(String id, Long timestamp, Double temperature) {
        this.id = id;
        this.timestamp = timestamp;
        this.temperature = temperature;
    }
}

然后调用该样例类编写代码:

public class source1_Collection {
    public static void main(String[] args) throws Exception {
        // 1、创建flink 环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);

        List<SensorReading> list=new ArrayList<>();
        list.add(new SensorReading("sensor_1",1624853494L,37.5));
        list.add(new SensorReading("sensor_3",1624853694L,36.5));
        list.add(new SensorReading("sensor_5",1624853794L,38.5));
        list.add(new SensorReading("sensor_2",1624853594L,39.5));
        list.add(new SensorReading("sensor_7",1624853994L,35.5));

        // 2、source
        DataStreamSource<SensorReading> dataStreamSource = env.fromCollection(list);

        // 3、sink
        dataStreamSource.print("sensor");

        env.execute("collectionSource");

    }
}

运行如图所示:
在这里插入图片描述

Source2_File

读取本地文件
先创建本地文件:
在这里插入图片描述
编写代码如下:

public class Source2_File {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        
        String filePath="E:\\ideaProjects\\flinkstu\\resource\\words.txt";
        DataStreamSource<String> inputDataStream = env.readTextFile(filePath);

        inputDataStream.print("filesource");
        env.execute("fileSource");
    }
}

运行如图所示:
在这里插入图片描述

Source3_Kafka

从kafka的 topic为sensor 中读取数据
编写代码如下:

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

        Properties prop = new Properties();
        prop.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.146.222:9092");
        prop.setProperty(ConsumerConfig.GROUP_ID_CONFIG,"sensor_group1");
        prop.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
        prop.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
        prop.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,"latest");

        DataStreamSource<String> dataStream = env.addSource(new FlinkKafkaConsumer011<String>("sensor", new SimpleStringSchema(), prop));
        dataStream.print("sensor");

        env.execute("sensor");

    }
}

运行结果如果所示,对topic生产数据后,控制台会同步输出对应数据内容:
在这里插入图片描述

Source4_MySource

安装样例类的格式,随机产生数据,并在控制台输出数据
代码如下:

public class Source4_MySource {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        DataStreamSource<Object> dataStram = env.addSource(new MySensorSource());
        dataStram.print("mySource");

        env.execute("mySourceDemo");
    }

    private static class MySensorSource implements org.apache.flink.streaming.api.functions.source.SourceFunction<Object> {
       boolean flag=true;
        @Override
        public void run(SourceContext<Object> sourceContext) throws Exception {
            while (flag){
                sourceContext.collect(
                        new SensorReading(
                                "sensor_"+new Random().nextInt(10),
                                System.currentTimeMillis(),
                                new Random().nextInt(9)+30.0
                        )
                );
                Thread.sleep(1000);
            }
        }

        @Override
        public void cancel() {
                flag=false;
        }
    }
}

运行结果如图所示:
在这里插入图片描述

Sink 展示

数据传输

Sink1_Kafka

Kafka 的sensor 生产数据时,利用程序将数据消费到 sensorout 中
代码如下:

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

        Properties prop = new Properties();
        prop.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.146.222:9092");
        prop.setProperty(ConsumerConfig.GROUP_ID_CONFIG,"sensor_group1");
        prop.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
        prop.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
        prop.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,"latest");

        DataStreamSource<String> dataStream = env.addSource(new FlinkKafkaConsumer011<String>("sensor", new SimpleStringSchema(), prop));
        SingleOutputStreamOperator<String> resultDataStream = dataStream.map(line -> {
            String[] wordLine = line.split(",");

            String sensorReadingStr = new SensorReading(
                    wordLine[0],
                    Long.parseLong(wordLine[1]),
                    Double.parseDouble(wordLine[2])
            ).toString();
            return sensorReadingStr;
        });

        resultDataStream.addSink(new FlinkKafkaProducer011<String>(
                "192.168.146.222:9092",
                "sensorout",
                new SimpleStringSchema()
                ));

        env.execute("sensor");
    }
}

运行如图所示:
对 topic sensor 生成数据时 topic sensorout 会同步消费出该数据
在这里插入图片描述

Sink2_Mysql

利用程序将Kafka topic sensor 中生成的数据对应插入到 mysql数据库中的sensor_temp 表中

代码如下:

public class Sink2_Mysql {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        Properties prop = new Properties();
        prop.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.146.222:9092");
        prop.setProperty(ConsumerConfig.GROUP_ID_CONFIG,"sensor_group1");
        prop.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
        prop.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
        prop.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,"latest");

        DataStreamSource<String> dataStream = env.addSource(new FlinkKafkaConsumer011<String>("sensor", new SimpleStringSchema(), prop));
        SingleOutputStreamOperator<SensorReading> resultDataStream = dataStream.map(line -> {
            String[] wordLine = line.split(",");

            SensorReading sensorReading = new SensorReading(
                    wordLine[0],
                    Long.parseLong(wordLine[1]),
                    Double.parseDouble(wordLine[2])
            );
            return sensorReading;
        });

        resultDataStream.addSink(new MyJdbcSink());


        env.execute("mysqlSinksensor");
    }

    private static class MyJdbcSink extends RichSinkFunction<SensorReading> {
        Connection connection=null;
        PreparedStatement insertstmt =null;
        PreparedStatement updatestmt =null;
        @Override
        public void open(Configuration parameters) throws Exception {
            connection= DriverManager.getConnection(
                    "jdbc:mysql://192.168.146.222:3306/flinkdemo?useSSL=false",
                    "root",
                    "1"
            );

            //准备预编译的插入语句
            insertstmt = connection.prepareStatement("insert into sensor_temp(id,temp) value(?,?)");
            //准备预编译的更新语句
            updatestmt = connection.prepareStatement("update sensor_temp set temp=? where id =?");

        }

        @Override
        public void invoke(SensorReading value, Context context) throws Exception {
           updatestmt.setDouble(1,value.getTemperature());
            updatestmt.setString(2,value.getId());
            updatestmt.execute();
            if (updatestmt.getUpdateCount()==0)
            {
                insertstmt.setString(1,value.getId());
                insertstmt.setDouble(2,value.getTemperature());
                insertstmt.execute();
            }
        }
        @Override
        public void close() throws Exception {
           connection.close();
        }

    }
}
//创建mysql 的库以及表
//mysql> create database flinkdemo;
//        Query OK, 1 row affected (0.00 sec)
//
//        mysql> use flinkdemo;
//        Database changed
//        mysql> create table sensor_temp(id varchar(32),temp double);
//        Query OK, 0 rows affected (0.01 sec)
//
//        mysql> desc sensor_temp;
//        +-------+-------------+------+-----+---------+-------+
//        | Field | Type        | Null | Key | Default | Extra |
//        +-------+-------------+------+-----+---------+-------+
//        | id    | varchar(32) | YES  |     | NULL    |       |
//        | temp  | double      | YES  |     | NULL    |       |
//        +-------+-------------+------+-----+---------+-------+
//        2 rows in set (0.01 sec)


运行结果如图所示:
只看最后一条数据,当生产了最后一条的数据后,对sensor_temp 表进行查询,发现已经将数据插入到该表中
在这里插入图片描述

Sink3_Redis

将本地文件 sensor.txt中的数据写入redis数据库内
本地文件如图:
在这里插入图片描述
代码如下:

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

        String filePath="E:\\ideaProjects\\flinkstu\\resource\\sensor.txt";
        DataStreamSource<String> inputStream = env.readTextFile(filePath);

        SingleOutputStreamOperator<SensorReading> dataStream = inputStream.map(line -> {
            String[] splits = line.split(",");
            return new SensorReading(splits[0],
                    Long.parseLong(splits[1]),
                    Double.parseDouble(splits[2]));
        });

        FlinkJedisPoolConfig config = new FlinkJedisPoolConfig.Builder()
                .setHost("192.168.146.222")
                .setPort(6379)
                .build();

        dataStream.addSink(new RedisSink<>(config, new RedisMapper<SensorReading>() {
            @Override
            public RedisCommandDescription getCommandDescription() {
                return new RedisCommandDescription(RedisCommand.HSET,"sensor_temp");
            }

            @Override
            public String getKeyFromData(SensorReading sensorReading) {
                return sensorReading.getId();
            }

            @Override
            public String getValueFromData(SensorReading sensorReading) {
                return sensorReading.getTemperature().toString();
            }
        }));
        env.execute("redisDemo");

    }
}

运行如下所示:
在这里插入图片描述

Transform

类型转换

Tranform1

代码如下:

public class Transform1 {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        String filePath = "E:\\ideaProjects\\flinkstu\\resource\\sensor.txt";
        DataStreamSource<String> inputStream = env.readTextFile(filePath);

        SingleOutputStreamOperator<SensorReading> mapStream = inputStream.map(new MapFunction<String, SensorReading>() {
            @Override
            public SensorReading map(String s) throws Exception {
                String[] split = s.split(",");
                return new SensorReading(split[0], Long.parseLong(split[1]), Double.parseDouble(split[1]));
            }
        });
        mapStream.print();

        SingleOutputStreamOperator<Integer> mapStream2 = inputStream.map(line -> {
            return line.length();
        });
       mapStream2.print();              

        env.execute("transform");
    }
}

运行结果如下:
在这里插入图片描述

Transform2
public class Transform2 {
            public static void main(String[] args) throws Exception {
                StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//        String filePath="D:\\Project\\FlinkStu\\resources\\sensor.txt";
//        DataStreamSource<String> inputStream = env.readTextFile(filePath);
                Properties prop = new Properties();
                prop.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.146.222:9092");
                prop.setProperty(ConsumerConfig.GROUP_ID_CONFIG,"sensor_group1");
                prop.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
                prop.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
                prop.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,"latest");
                DataStreamSource<String> inputStream = env.addSource(new FlinkKafkaConsumer011<String>("sensor", new SimpleStringSchema(), prop));

                SingleOutputStreamOperator<SensorReading> mapStream = inputStream.map(new MapFunction<String, SensorReading>() {
                    @Override
                    public SensorReading map(String s) throws Exception {
                        String[] split = s.split(",");
                        return new SensorReading(split[0], Long.parseLong(split[1]), Double.parseDouble(split[2]));
                    }
                });

                KeyedStream<SensorReading, Tuple> keyByStream = mapStream.keyBy("id");
                SingleOutputStreamOperator<SensorReading> resultStream =
//                keyByStream.max("temperature");     //只返回原值
//                keyByStream.min("temperature");
//                keyByStream.maxBy("temperature");   //返回一整条信息,不只是单个值,而是值所在的整个信息
                        keyByStream.minBy("temperature");

                resultStream.print();

        SingleOutputStreamOperator<SensorReading> reduceStream1 =
                keyByStream.reduce(new ReduceFunction<SensorReading>() {
            @Override
            public SensorReading reduce(SensorReading sensorReading, SensorReading t1) throws Exception {
                return new SensorReading(sensorReading.getId(),
                        sensorReading.getTimestamp(),
                        Math.min(t1.getTemperature(), sensorReading.getTemperature()));
            }
        });
// 另一种写法
        SingleOutputStreamOperator<SensorReading> reduceStream2 = keyByStream.reduce((curSensorReading, newSensorReading) -> {
            return new SensorReading(curSensorReading.getId(),
                    curSensorReading.getTimestamp(),
                    Math.min(newSensorReading.getTemperature(), curSensorReading.getTemperature()));
        });

        env.execute("transform2");
    }
}

运行如下所示:
在这里插入图片描述

Transform3
public class Transform3 {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//        String filePath="D:\\Project\\FlinkStu\\resources\\sensor.txt";
//        DataStreamSource<String> inputStream = env.readTextFile(filePath);
        Properties prop = new Properties();
        prop.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.146.222:9092");
        prop.setProperty(ConsumerConfig.GROUP_ID_CONFIG,"sensor_group1");
        prop.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
        prop.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
        prop.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,"latest");
        DataStreamSource<String> inputStream = env.addSource(new FlinkKafkaConsumer011<String>("sensor", new SimpleStringSchema(), prop));

        SingleOutputStreamOperator<SensorReading> mapStream = inputStream.map(new MapFunction<String, SensorReading>() {
            @Override
            public SensorReading map(String s) throws Exception {
                String[] split = s.split(",");
                return new SensorReading(split[0], Long.parseLong(split[1]), Double.parseDouble(split[2]));
            }
        });

        SplitStream<SensorReading> splitStream = mapStream.split(new OutputSelector<SensorReading>() {
            @Override
            public Iterable<String> select(SensorReading sensorReading) {
                if (sensorReading.getTemperature() > 38.0) {
                    return Collections.singletonList("high");
                } else if(sensorReading.getTemperature()<36.0){
                    return Collections.singletonList("low");
                } else {
                    return Collections.singletonList("normal");
                }
            }
        });
        DataStream<SensorReading> high = splitStream.select("high");
        DataStream<SensorReading> low = splitStream.select("low");
        DataStream<SensorReading> normal = splitStream.select("normal");
        high.print("high");
        low.print("low");
        normal.print("normal");

        //合流  union   类型必须一致,否则无法合并
        DataStream<SensorReading> unionDataStream = high.union(low, normal);
        unionDataStream.print("union");
        
        //connect  合流   合并在两个流,是不同的类型
        SingleOutputStreamOperator<Tuple2<String, Double>> warningDataStream = high.map(new MapFunction<SensorReading, Tuple2<String, Double>>() {
            @Override
            public Tuple2<String, Double> map(SensorReading sensorReading) throws Exception {
                return new Tuple2<>(sensorReading.getId(), sensorReading.getTemperature());
            }
        });

        ConnectedStreams<Tuple2<String, Double>, SensorReading> connectStream = warningDataStream.connect(normal);

        SingleOutputStreamOperator<Object> resultStream = connectStream.map(new CoMapFunction<Tuple2<String, Double>, SensorReading, Object>() {
            @Override
            public Object map1(Tuple2<String, Double> stringDoubleTuple2) throws Exception {
                return new Tuple3<>(stringDoubleTuple2.f0, stringDoubleTuple2.f1, "发烧了");
            }

            @Override
            public Object map2(SensorReading sensorReading) throws Exception {
                return new Tuple2<>(sensorReading.getId(), "健康,没有发烧");
            }
        });
        resultStream.print("connect");
        env.execute("transform3");
    }
    private static class MyRichMapFunction extends RichMapFunction<SensorReading,Tuple2<String,Integer>>{

        @Override
        public Tuple2<String, Integer> map(SensorReading sensorReading) throws Exception {
            return null;
        }
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值