Flink入门教程(二)

Flink入门教程(一)中提前感受了一下如何使用flink处理数据。这里再介绍下特点。

一、核心功能

Flink的核心是一个流式的数据流执行引擎,针对数据流的分布式计算提供了数据分布、数据通信以及容错机制。

  • Flink支持实时Streaming和批处理Batch
  • DataSet API,对静态数据进行批处理操作,将静态数据抽象成分布式数据集,可以方便的使用Flink提供的各种操作符对分布式数据集进行处理。
  • DataStream API,对数据流进行流处理,将流式数据抽象成分布式的数据流,可以方便的对分布式数据流进行各种操作。
  • Table API,对结构化数据进行查询操作,将结构化数据抽象成关系表,并通过类SQL的DSL对关系表进行各种查询操作。
  • Flink ML,机器学习库,提供机器学习Pipelines API并实现了多种机器学习算法。
  • Gelly,Flink的图计算库,提供了图计算的相关API及多种图计算算法实现。

二、测试demo

对flink程序最好的学习方式就是实际写代码测试,下面我们做几个常见的flink功能测试。

测试代码已经上传GitHub,https://github.com/fanyun7654/flink-test,可以去下载完整的demo,文章里面只介绍代码功能。如果有用可以给一颗star

  • flink table SQL的测试

我目前的开发最需要的是使用flink的流式引擎处理部分,所以这里也跳过基础直接开始流式处理的测试。首先初始化流式处理环境,这里我使用了table + SQL的功能,功能是监控并且从kafka获取消息,然后吧获取的消息使用table API 创建一个虚拟表,然后使用flink提供的SQL 功能对虚拟表进行操作。

package com.fanyun.flink;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fanyun.flink.destination.sql.MysqlSink;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.restartstrategy.RestartStrategies;
import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.api.common.time.Time;
import org.apache.flink.api.java.tuple.Tuple1;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.api.java.typeutils.RowTypeInfo;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer010;
import org.apache.flink.table.api.StreamQueryConfig;
import org.apache.flink.table.api.Table;
import org.apache.flink.table.api.java.StreamTableEnvironment;
import org.apache.flink.table.api.TableEnvironment;
import org.apache.flink.types.Row;
import org.apache.kafka.clients.consumer.ConsumerConfig;

import java.util.Properties;

import static org.apache.flink.api.common.typeinfo.BasicTypeInfo.STRING_TYPE_INFO;

public class KafkaToFlink {
    public static void main(String[] args) throws Exception {
        //初始化流式处理环境
        final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        //初始化table环境
        StreamTableEnvironment tableEnv = TableEnvironment.getTableEnvironment(env);
        //设置此可以屏蔽掉日记打印情况,运行环境配置
//      env.getConfig().disableSysoutLogging();
        env.getConfig().setRestartStrategy(RestartStrategies.fixedDelayRestart(4, 10000));
        env.enableCheckpointing(500);      //启动检查点
        //toAppendStream方法的查询配置
        StreamQueryConfig qConfig = tableEnv.queryConfig();
        //空闲状态保持时间,最小最大时间
        qConfig.withIdleStateRetentionTime(Time.milliseconds(5), Time.minutes(6));

        //kafka配置信息
        Properties properties = new Properties();
        properties.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
//        properties.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "10.201.82.55:9092");
        properties.setProperty(ConsumerConfig.GROUP_ID_CONFIG, "test");

        //创建flink kafka消费者,不用版本功能介绍
        // https://ci.apache.org/projects/flink/flink-docs-release-1.7/dev/connectors/kafka.html
        FlinkKafkaConsumer010<String> myConsumer = new FlinkKafkaConsumer010<>(
                "topic",
                new SimpleStringSchema(),
                properties);

        DataStream<String> sourceStream = env.addSource(myConsumer);
        //将来源的数据转为DataStream
        DataStream<Tuple3<String,String,String>> stream = sourceStream.map(new JobMapFun());
        //注册临时表
        tableEnv.registerDataStream("myTable2", stream, "din,type,version");
        //写sql语句
        String sql = "SELECT din,type,version FROM myTable2";
        //执行sql查询
        Table table = tableEnv.sqlQuery(sql);
        //打印查看数据
        DataStream<Tuple2<Boolean, Row>> wcDataStream = tableEnv.toRetractStream(table, Row.class);
        wcDataStream.print();

        //sql中的字段的类型
        RowTypeInfo typeInformations = new RowTypeInfo(STRING_TYPE_INFO);
        //将数据追加到Table中
        DataStream<Row> retractStream = tableEnv.toAppendStream(table, typeInformations, qConfig);
        //输出查询结果,value.f1就是Row
        desStream.print();
        retractStream.print();

        //将获取的数据直接输出
//        sourceStream.map(new MapFunction<String, String>() {
//            @Override
//            public String map(String value) throws Exception {
//                return "Stream Value ========== " + value;
//            }
//        }).print();
        env.execute("flink kafka test");
    }

    public static class JobMapFun implements MapFunction<String, Tuple3<String,String,String>> {
        @Override
        public Tuple3<String,String,String> map(String json) {
            JSONObject outJson = JSON.parseObject(json);
            String din = outJson.get("din").toString();
            System.out.println("-----------Din:"+ din);
            String type = outJson.get("type").toString();
            String version = outJson.get("version").toString();
            Long timestamp = Long.parseLong(outJson.get("timestamp").toString());
            return new Tuple3<String, String, String>(din,type,version);
        }
    }

}

不过对于flink程序的运行有点问题,首先我是在idea下面编写的,但是idea下直接启动调试是有点问题的。idea环境下运行flink程序我理解是启动了一个低配版的flink环境,比如没有web管理后台,带来的问题是无法查看task的执行情况,这对于编写测试代码还是有很大影响。

所以目前我的测试办法是对代码打包之后放在linux环境下面执行,这样就可以使用web管理台或者查看日志。

另外就是打包的问题,官方建议把程序需要的jar包单独打包。所以这里我在打包的时候也选择了这种方式,然后把需要的jar包拷贝到target的 lib目录下,然后把lib目录下的jar包全部上传到服务器flink安装目录的lib下面。如何打fat包跟程序包在pom.xml文件中都进行了配置,可以自由选择。

这里有另外一个可能的坑,如果你也把需要的jar包上传到flink的lib目录下面,一定要注意上传完直接需要重启flink。根据我的测试,如果不重启会出现jar包明明有但是找不到的情况。

  • flink数据处理之后写入mysql
  • flink数据处理之后写入postgresql
  • flink数据处理之后写入mongoDB

上面三种数据库mysql、postgresql、mongoDB其实实现方式差不多,都需要继承

RichSinkFunction<Tuple3<String,String,String>>

这个类,然后实现自己的Sink方法,比如mysql的,主要是实现 

invoke 

方法。当然直接下载我这个程序是启动不起来的,因为没有我的kafka数据,所以要运行起来还需要搭建自己的kafka环境,并且给kafka写入测试数据。写入测试数据可以用下面的测试代码,不过这个方法有一个问题写入的kafka数据格式需要配置格式,demo里面并没有实现这一点,会在后面再进行测试实现这一点。

KafkaToFlinkToKafka
  • flink数据处理之后写入kafka

 

 

 

 

展开阅读全文

没有更多推荐了,返回首页