Flink基础概述

422 阅读4分钟

这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战

概述

概念

分布式处理引擎, 用于对无界和有界数据流进行有效态计算,以内存执行速度和任意规模来执行计算。

特点

  • 批流一体: 统一批处理,流处理
  • 分布式: Flink程序可以运行在多台机器上
  • 高性能: 处理性能比较高
  • 高可用: 支持高可用性(HA)
  • 准确: 数据处理的准确性

核心组成

  • API & Libraries: DataStreamAPI(Stream Processing) DataSet API (Batch Processing) CEP Table FinkML Gelly Table
  • core: Runtime(Distributed Streaming Dataflow)
  • deploy: Local(Single JVM) Cluster(standalone, YARN) Cloud(GCE, EC2)

处理模型: 流处理与批处理

Flink专注于无限流处理, 有限流处理是无限流处理的一种特殊情况, 封装了DataStream进行流处理, 封装了DataSet进行批处理, 是批流一体的处理引擎, 提供了Table API/SQL 统一了批处理和流处理

应用场景

  • 实时ETL
  • 实时报表
  • 监控预警
  • 在线系统

体系

角色

JobManager

  • 协调分布式执行,调度task,协调检查点(checkPoint), 协调失败后恢复
  • Flink运行时至少存在一个master处理器,配置高可用可能存在多个, 其中一个是leader, 其它是standby

TaskManager

  • worker, 主要职责是从JobManager接到任务, 部署和启动任务, 接收上游的数据并处理
  • JVM中的一个或多个线程中执行任务的工作节点

体系结构

程序构成

Flink 程序的基本构建块是流和转换,流是数据记录流,转换是将一个或多个流输入, 产生一个或多个输出流

  • Source

    数据源, 定义Flink从哪里加载数据, 主要四种: 基于本地的source, 基于文件的source, 基于套接字的source,自定义的source

  • Transformation

    数据转换的各种操作, 也称之为算子, 有Map/FlatMap/Filter/KeyBy/Reduce/Window等, 可以将数据转换计算成想要的数据

  • Sink

    接收器, Flink将转换计算后的数据发送的地点, 定义了结果数据的输出方向, 常用的有写入文件, 打印出来, 写入socket,自定义的sink

Task和SubTask

  • Task是一个阶段多个功能相同SubTask的集合
  • SubTask是Flink中任务最小执行单元, 是一个Java类的实例

Operator Chain(操作链)

Flink的所有操作都成为Operator, 客户端在提交任务时会对Operator进行优化, 能进行合并的Operator会合并为一个Operator, 合并后的Operator成为Operator chain, 每个执行链会在TaskManager上一个独立的线程执行

任务槽和槽共享

为了控制一个worker能接受多少个task, worker通过task slot来控制(至少一个)

  • 任务槽

    标识TaskManger拥有资源的固定大小的子集, 一般来说槽的个数和CPU的核数相等.将内存划分多个槽中(平分)。

    内存被划分不同的slot之后可以获得好处:

    • 最多能同时并发执行的任务可以控制
    • slot有独占的内存空间, 作业之间不受影响, 内存独占,但CPU共享
  • 槽共享

    shuffle会有网络操作和IO开销,默认情况下, Flink允许子任务共享插槽,只要来自同一个作业, 槽可以保存整个作业的管道

部署

Flink 支持多种安装模式

  • Local: 单机模式, 一般本地开发调试
  • Standalone: 独立, Flink自带集群, 自己管理资源调度
  • Yarn模式: 计算资源统一由Hadoop YARN 管理, 生产环境应用较多

基础环境

  • JDK1.8及以上(配置JAVA_HOME环境变量)
  • ssh免密码登录

standalone

  • 下载文件并解压到相关目录

  • 修改配置文件

    ## flink-conf.yaml
    jobmanager.rpc.address: 192.168.1.3
    taskmanager.numberofTaskSlots:2
    
    ## masters
    192.168.1.3: 8081
    
    ## slaves
    192.168.1.3
    192.168.1.4
    192.168.1.5
    
  • 发送到另外两台节点上

     scp -r flink-1.13.1 192.168.1.5:$PWD
    
  • 配置环境变量

    vim /etc/profile
    export FLINK_HOME=/opt/flink/flink-1.13.1
    export PATH=.:$PATH:$JAVA_HOME/bin:$FLINK_HOME/bin
    . /etc/profile
    cd /flink-1.13.1/bin
    ./start-cluster.sh
    

    部署成功

    <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>3.2.4</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>shade</goal>
                            </goals>
                            <configuration>
                                <filters>
                                    <filter>
                                        <artifact>*:*</artifact>
                                        <exclude>META-INF/*.SF</exclude>
                                        <exclude>META-INF/*.DSA</exclude>
                                        <exclude>META-INF/*.RSA</exclude>
                                    </filter>
                                </filters>
                            </configuration>
                        </execution>
                    </executions>
    
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>7</source>
                        <target>7</target>
                    </configuration>
                </plugin>
            </plugins>
    

最简单案例

批处理

pom 文件依赖导入

<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-java</artifactId>
    <version>1.13.0</version>
</dependency>
<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-clients_2.12</artifactId>
    <version>1.13.0</version>
</dependency>

具体代码

这里需要注意的是FlatMapFunction类不能用lambda表达式,会缺失泛型信息,报错

public class WordCountBatch {

    public static void main(String[] args) throws Exception {
        ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
        String input ="C:\\Users\\Administrator\\Desktop\\word.txt";
        DataSource<String> dataSource = env.readTextFile(input);
        FlatMapOperator<String, Tuple2<String, Integer>> wordDealOpt = dataSource.flatMap(new SplitFunc());
        UnsortedGrouping<Tuple2<String, Integer>> wordGroup = wordDealOpt.groupBy(0);
        DataSet<Tuple2<String, Integer>> sum = wordGroup.sum(1);
        sum.writeAsText("C:\\Users\\Administrator\\Desktop\\output");
        env.execute("word Count");
    }

    static class SplitFunc implements FlatMapFunction<String, Tuple2<String , Integer>> {

        @Override
        public void flatMap(String value, Collector<Tuple2<String, Integer>> collector) throws Exception {
            String[] words = value.split(" ");
            for (String word: words){
                Tuple2<String, Integer> wordDeal = new Tuple2<>(word, 1);
                collector.collect(wordDeal);
            }
        }
    }
}

流处理

前置准备

  • 安装netcat

    yum install -y nc
    nc -lk 10000
    nc 192.168.1.3 10000
    

pom文件依赖导入

<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-streaming-java_2.12</artifactId>
    <version>1.13.0</version>
</dependency>
<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-clients_2.12</artifactId>
    <version>1.13.0</version>
</dependency>

具体代码

public class WordCountStream {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        DataStreamSource<String> streamSource = env.socketTextStream("192.168.1.3", 10000);
        SingleOutputStreamOperator<Tuple2<String, Integer>> singleOutputStreamOperator = streamSource.flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {

            @Override
            public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception {
                for (String word : value.split(" ")) {
                    out.collect(Tuple2.of(word, 1));
                }
            }
        });
        SingleOutputStreamOperator<Tuple2<String, Integer>> result = singleOutputStreamOperator.keyBy(0).sum(1);
        result.print();
        env.execute("word Count");
    }
}