Flink Environment & Source

Environment

Flink 可以在各种上下文环境中执行,不同的环境,代码提交的过程有所不同。这就要求在提交作业执行计算时,首先必须获取当前Flink的运行环境,从而建立起与Flink框架之间的联系,只有获取了上下文环境信息,才能将具体的任务调度到不同的TaskManager上执行。

1、创建执行环境

编写Flink程序的第一步,就是创建执行环境。要获取的执行环境,是StreamExecutionEnvironment类的对象,这是所有Flink程序的基础。在代码中创建执行环境的方式,就是调用这个类的静态方法,具体有以下三种。

1. getExecutionEnvironment

最简单的方式,就是直接调用getExecutionEnvironment方法。它会根据当前运行的上下文直接得到正确的结果:如果程序是独立运行的,就返回一个本地执行环境;如果是创建了jar包,然后从命令行调用它并提交到集群执行,那么就返回集群的执行环境。也就是说,这个方法会根据当前运行的方式,自行决定该返回什么样的运行环境。

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

这种“智能”的方式不需要我们额外做判断,用起来简单高效,是最常用的一种创建执行环境的方式。

2. createLocalEnvironment.

这个方法返回一个本地执行环境。可以在调用时传入一个参数,指定默认的并行度;如果不传入,则默认并行度就是本地的CPU核心数。

 StreamExecutionEnvironment localEnv = StreamExecutionEnvironment.createLocalEnvironment();

3. createRemoteEnvironment

这个方法返回集群执行环境。需要在调用时指定JobManager的主机名和端口号,并指定要在集群中运行的Jar包。

        StreamExecutionEnvironment remoteEnv = StreamExecutionEnvironment.createRemoteEnvironment("host", // JobManager主机名
                1234, // JobManager进程端口号
                "path/to/jarFile.jar"// 提交给JobManager的JAR包
        );

Source

 Flink框架可以从不同的来源获取数据,将数据提交给框架进行处理, 我们将获取数据的来源称之为数据源(Source)。

准备工作

引入依赖

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.16</version>
    <scope>provided</scope>
</dependency>

创建实体类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 水位 监控器 用于接收水位数据
 * id 传感器编号
 * ts 时间戳
 * vc 水位
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class WaterSensor {

    public String id;
    public long ts;
    public Integer vc;
}

从集合中读取数据

一般情况下,可以将数据临时存储到内存中,形成特殊的数据结构后,作为数据源使用。这里的数据结构采用集合类型是比较普遍的。

import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.wdh01.bean.WaterSensor;

import java.util.Arrays;
import java.util.List;

/**
 * 从集合读取数据
 */
public class Flink01_Source_Collection {
    public static void main(String[] args) throws Exception {
        //1、获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(2);//若 并行度1 按顺序读取数据,否则不按顺序
        //2、准备集合
        List<WaterSensor> waterSensors = Arrays.asList(
                new WaterSensor("ws_001", 1577844001L, 45),
                new WaterSensor("ws_002", 1577844015L, 43),
                new WaterSensor("ws_003", 1577844020L, 42));
        //3、从集合读取数据
        DataStreamSource<WaterSensor> waterSensorDataStreamSource = env.fromCollection(waterSensors);
        //4、打印
        waterSensorDataStreamSource.print();
        //5、执行
        env.execute();
    }
}

从文件中读取数据

import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.wdh01.bean.WaterSensor;

/**
 * 从文件读取数据
 */
public class Flink02_Source_File {
    public static void main(String[] args) throws Exception {
        //1、获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);//若 并行度1 按顺序读取数据,否则不按顺序
        // 2、从文件读取数据
        DataStreamSource<String> stringDataStreamSource = env.readTextFile("input/sensor");
        //3、转换 javabean 打印数据 new MapFunction<String, WaterSenso String 是 方法的入参泛型,WaterSenso 是出参类型
        stringDataStreamSource.map(new MapFunction<String, WaterSensor>() {
            public WaterSensor map(String value) throws Exception {
                String[] split = value.split(",");
                return new WaterSensor(split[0], Long.parseLong(split[1]), Integer.parseInt(split[2]));
            }
        }).print();
        //4、执行
        env.execute();
    }
}

说明

也可以从 hdfs 文件系统读取数据,
  1. 参数可以是目录也可以是文件
  2. 路径可以是相对路径也可以是绝对路径
  3. 相对路径是从系统属性user.dir获取路径: idea下是project的根目录, standalone模式下是集群节点根目录
  4. 也可以从hdfs目录下读取, 使用路径:hdfs://...., 由于Flink没有提供hadoop相关依赖, 需要pom中添加相关依赖:
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-client</artifactId>
    <version>2.7.2</version>
    <scope>provided</scope>
</dependency>

从socket中读取数据

import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

/**
 * 从端口读取数据
 */
public class Flink03_Source_Socket {
    public static void main(String[] args) throws Exception {
        //1、获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);//若 并行度1 按顺序读取数据,否则不按顺序
        //2、从端口读取数据
        DataStreamSource<String> socketTextStream = env.socketTextStream("hadoop103", 9998);

        //3、打印
        socketTextStream.print();
        //4、执行
        env.execute();
    }
}

从kafka中读取数据

引入依赖

<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-connector-kafka_2.11</artifactId>
    <version>1.12.0</version>
</dependency>
import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
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.util.Properties;

/**
 * kafka 读取数据
 */
public class Flink04_Source_Kafka {
    public static void main(String[] args) throws Exception {
        //1、获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);//若 并行度1 按顺序读取数据,否则不按顺序
        //2、配置 kafka
        Properties properties = new Properties();
        properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop103:9092");
        properties.put(ConsumerConfig.GROUP_ID_CONFIG, "Flink0214");
        //3、读取数据
        DataStreamSource<String> test =
                env.addSource(new FlinkKafkaConsumer<String>("test", new SimpleStringSchema(), properties));
        //4、打印
        test.print();
        env.execute();
        //主机上 测试 bin/kafka-console-producer.sh --topic test --broker-list hadoop103
    }
}

自定义source

import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.SourceFunction;
import org.wdh01.bean.WaterSensor;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

/**
 * 自定义 source
 */
public class Flink05_Source_MySource {
    public static void main(String[] args) throws Exception {
        //1、获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);//若 并行度1 按顺序读取数据,否则不按顺序
        //2、读取数据
        DataStreamSource<WaterSensor> ds103 = env.addSource(new MySource("hadoop103", 9998));
        //3、打印
        ds103.print();
        //4、执行
        env.execute();

    }

    /**
     * 自定义 Source,模拟 端口 source
     */
    public static class MySource implements SourceFunction<WaterSensor> {
        //定义属性 主机和 端口
        public String host;
        public Integer port;
        private boolean flag = true;
        Socket socket = null;
        BufferedReader reader = null;

        public MySource() {
        }

        public MySource(String host, Integer port) {
            this.host = host;
            this.port = port;
        }

        public void run(SourceContext ctx) throws Exception {
            //创建输入流
            socket = new Socket(host, port);
            reader = new
                    BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
            while (flag) {
                // 读取数据
                String line = reader.readLine();
                while (flag && line != null) {
                    //接收数据 并发送 flink
                    String[] s = line.split(",");
                    WaterSensor waterSensor = new WaterSensor(s[0], Long.parseLong(s[1]), Integer.parseInt(s[2]));
                    ctx.collect(waterSensor);
                    line = reader.readLine();
                }
            }
        }

        public void cancel() {
            flag = false;
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

posted @ 2022-02-15 18:21  晓枫的春天  阅读(170)  评论(0编辑  收藏  举报