大数据开发快速入门Flink(第四十四篇)

131 阅读4分钟

一、什么是Flink

Flink是一个开源的分布式高性能高可用准确的流处理框架。支持流(Stream)处理(实时计算)和批(Batch)处理(离线计算)

  1. 分布式:可以运行在很多台机器上
  2. 高性能:处理性能很高
  3. 高可用:支持程序的自动重启等机制
  4. 准确的:可以保证处理数据的准确性
1.1、Flink三大核心组件
  1. Data Source
  2. Transformations
  3. Data Sink
1.2、Fink的流处理和批处理
  1. 在大数据处理领域,批处理和流处理一般被认为是两种不同的任务,一个大数据框架一般会被设计为只能处理其中一个任务
  2. Flink通过灵活的执行引擎,能够同时支持批处理和流处理

流处理系统和批处理系统最大的不同在于节点之间的数据传输方式:

  • 流处理系统:当一条数据被处理完成后,序列化到缓存中,然后立刻通过网络传输到下一个节点,由下一个节点继续处理。这个是典型的一条一条处理(低延迟要求
  • 批处理系统:当一条数据被处理完成后,序列化到缓存中,此时并不会立刻通过网络传输到下一个节点,当缓存写满的时候,它会持久化到本地磁盘上面,当所有数都被处理完成之后,才开始将处理后的数据通过网络传输到下一个节点(高吞吐量要求

Flink同时支持这两种模式,Flink以固定的缓存块为单位进行网络数据传输,用户可以通过缓存块超时值指定缓存块的传输时机,如果缓存块的超时值为0,则Flink的数据传输方式类似于前面所说的流处理系统的标准模型,此时系统可以获得最低的处理延迟。如果缓存块的超时值为无限大,则Flink的数据传输方式,类似于前面所说的批处理系统的标准模型,此时系统可以获取最高的吞吐量。其实底层还是流式计算模型,批处理只是一个极限的特例而已

1.3、Flink的三种数据传输模型
  1. Record-by-record:make buffer as full 一条一条执行
  2. Batch:Retaion all buffers 批处理执行
  3. Pipelined:ship buffer when actually full 缓存块执行
1.4、实时计算框架对比
产品StormSparkStreamingFlink
模型Native(来一条一条处理)Mirco-Batch(一小批一小批处理)Native
API组合式(只有基础api)声明式(封装好的高级函数)声明式
语义At-least-once(最少一次,消息不会丢失,但是可能会重复)Exectly-once(恰好一次。消息有且仅会被传输一次)Exectly-once
容错机制Ack(每发出一条数据,需要收到回复)Checkpoint(JobManager定时触发)Checkpoint
状态管理基于DStream基于操作
延时LowMediumLow
吞吐量LowHighHigh

二、Flink代码入门

idea引入scala

image-20230108202448807

  1. pom依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    ​
        <groupId>com.strivelearn</groupId>
        <artifactId>flink-study</artifactId>
        <version>1.0-SNAPSHOT</version>
    ​
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    ​
        <dependencies>
            <!--开发离线代码依赖-->
            <dependency>
                <groupId>org.apache.flink</groupId>
                <artifactId>flink-java</artifactId>
                <version>1.16.0</version>
            </dependency>
    ​
            <!--开发实时代码依赖-->
            <dependency>
                <groupId>org.apache.flink</groupId>
                <artifactId>flink-streaming-java</artifactId>
                <version>1.16.0</version>
                <scope>provided</scope>
            </dependency>
    ​
            <dependency>
                <groupId>org.apache.flink</groupId>
                <artifactId>flink-scala_2.12</artifactId>
                <version>1.16.0</version>
            </dependency>
    ​
            <dependency>
                <groupId>org.apache.flink</groupId>
                <artifactId>flink-streaming-scala_2.12</artifactId>
                <version>1.16.0</version>
            </dependency>
    ​
            <!--flink客户端依赖-->
            <dependency>
                <groupId>org.apache.flink</groupId>
                <artifactId>flink-clients</artifactId>
                <version>1.16.0</version>
            </dependency>
    ​
        </dependencies>
    </project>
    
  2. Flink Job开发步骤

    • 获取一个执行环境
    • 加载/创建 初始化数据
    • 指定操作数据的transcation算子
    • 指定数据目的地
    • 调用execute触发执行程序

    注意:Flink程序是延迟计算的,只有最后调用execute方法的时候才会真正触发执行程序

  3. 代码案例场景:

    通过socket实时产生一些单词,使用Flink实时接收数据,对指定时间内(比如:2秒)的数据进行聚合统计并且把时间窗口内计算的结果打印出来

  4. 先要安装linux nc -l 命令,端口测试,TCP服务

    yum install nc

    安装完成后,在服务器端执行以下命令,实现TCP方式监听5000端口,且显示输出命令:

    nc -l [port number] -v

    eg:

    nc -l 5000 -v

package com.strivelearn.flink;
​
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.TimeCharacteristic;
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.api.windowing.time.Time;
import org.apache.flink.util.Collector;
​
/**
 * @author strivelearn
 * @version SocketWindowWordCountJava.java, 2023年01月08日
 */
public class SocketWindowWordCountJava {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment environment = StreamExecutionEnvironment.getExecutionEnvironment();
        DataStreamSource<String> text = environment.socketTextStream("bigdata01", 9001);
        environment.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime);
        SingleOutputStreamOperator<Tuple2<String, Integer>> wordCount = text.flatMap(new FlatMapFunction<String, String>() {
            @Override
            public void flatMap(String line, Collector<String> collector) throws Exception {
                String[] words = line.split(" ");
                for (String word : words) {
                    collector.collect(word);
                }
            }
        }).map(new MapFunction<String, Tuple2<String, Integer>>() {
            @Override
            public Tuple2<String, Integer> map(String s) throws Exception {
                return new Tuple2<>(s, 1);
            }
        }).keyBy(tup -> tup.f0).timeWindow(Time.seconds(2)).sum(1);
        // 使用一个线程执行打印操作
        wordCount.print().setParallelism(1);
        // 执行程序
        environment.execute("SocketWindowWordCountJava");
​
    }
}

image-20230108214232354

image-20230108214240324