初识Flink之流处理(二)

DataStream API介绍

什么能被转化成流?

Flink的Java和Scala DataStream API 可以将任何可序列化的对象转化为流。
Flink 自带的序列化器有

基本类型,即 String、Long、Integer、Boolean、Array
复合类型:Tuples、POJOs 和 Scala case classes
而且 Flink 会交给 Kryo 序列化其他类型。也可以将其他序列化器和 Flink 一起使用。特别是有良好支持的 Avro。
Java tuples 和 POJOs
Flink 的原生序列化器可以高效地操作 tuples 和 POJOs
Tuples
对于 Java,Flink 自带有 Tuple0 到 Tuple25 类型。

Tuple2<String, Integer> person = Tuple2.of("Jack", 15);
String name = person.f0;
Integer age = person.f1;

POJOs
如果满足以下条件,Flink 将数据类型识别为 POJO 类型(并允许“按名称”字段引用):

该类是公有且独立的(没有非静态内部类)
该类有公有的无参构造函数
类(及父类)中所有的所有不被 static、transient 修饰的属性要么是公有的(且不被 final 修饰),要么是包含公有的 getter 和 setter 方法,这些方法遵循 Java bean 命名规范。

public class Person {

    public String name;

    public Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    ....
}

Flink 的序列化器支持的 POJO 类型数据结构升级。
下面是一个完整的示例:

import org.apache.flink.api.common.functions.FilterFunction;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

/**
 * @author Jack House
 * @date 2021年03月20日 11:08:20
 */
public class Example {

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

        DataStream<Person> flinstones = env.fromElements(new Person("Nico",25), new Person("Hores", 22), new Person("Jack", 28));

        DataStream<Person> adults = flinstones.filter(new FilterFunction<Person>() {
            @Override
            public boolean filter(Person person) throws Exception {
                return person.age >= 25;
            }
        });

        adults.print();

        env.execute();
    }
}

那么在这个示例执行中会出现什么问题呢?
ava.lang.NoClassDefFoundError: org/apache/flink/streaming/api/datastream/DataStream
在这里插入图片描述
这个是由于加了scope标签造成的。

Stream 执行环境
每个 Flink 应用都需要有执行环境,在该示例中为 env。流式应用需要用到 StreamExecutionEnvironment。

DataStream API 将你的应用构建为一个 job graph,并附加到 StreamExecutionEnvironment 。当调用 env.execute() 时此 graph 就被打包并发送到 JobManager 上,后者对作业并行处理并将其子任务分发给 Task Manager 来执行。每个作业的并行子任务将在 task slot 中执行。

注意,如果没有调用 execute(),应用就不会运行。
在这里插入图片描述
此分布式运行时取决于你的应用是否是可序列化的。它还要求所有依赖对集群中的每个节点均可用。
基本的 stream sink
上述示例用 adults.print() 打印其结果到 task manager 的日志中(如果运行在 IDE 中时,将追加到你的 IDE 控制台)。它会对流中的每个元素都调用 toString() 方法。

输出看起来类似于

1> Fred: age 35
2> Wilma: age 35
1> 和 2> 指出输出来自哪个 sub-task(即 thread)

下面说说flink-training中的练习问题吧

public class RideCleansingSolution extends ExerciseBase {

    public static void main(String[] args) throws Exception {

        //初始化Flink的Streaming(流计算)上下文执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        //将 job或运算符的并行度设置为x,即运算符的并行任务数。
        env.setParallelism(ExerciseBase.parallelism);

        //添加数据源,并将数据组装成数据流
        DataStream<TaxiRide> rides = env.addSource(rideSourceOrTest(new TaxiRideGenerator()));
        //过滤数据,并返回过滤后的数据流
        DataStream<TaxiRide> filteredRides = rides.filter(new NYCFilter());
        //打印过滤后的数据流
        printOrTest(filteredRides);
        //执行flink应用
        env.execute("Taxi Ride Cleansing");
    }

    /**
     * 纽约过滤器类
     */
    public static class NYCFilter implements FilterFunction<TaxiRide> {

        /**
         *
         * @param taxiRide 传入坐标
         * @return boolean true 在纽约内 false 在纽约之外
         * @throws Exception
         */
        @Override
        public boolean filter(TaxiRide taxiRide) throws Exception {
            return GeoUtils.isInNYC(taxiRide.startLon,taxiRide.startLat) && GeoUtils.isInNYC(taxiRide.endLon, taxiRide.endLat);
        }
    }
}

这是java写法。当然同一一个项目里面也可以写scala,具体设置如下:
在这里插入图片描述
首先要安装scala插件,然后电脑上也要安装scala-sdk-xxx ,当然安装的版本和项目相对应。
在这里插入图片描述
然后在项目里面新建就可以看到scala class
在这里插入图片描述
之前上面的练习是java写,下面说说scala写法:

object RideCleansingSolution {

  def main(args: Array[String]): Unit = {

    //设置执行环境
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    //设置并行任务数
    env.setParallelism(ExerciseBase.parallelism)

    //获取数据源
    val rides = env.addSource(rideSourceOrTest(new TaxiRideGenerator()))

    //过滤数据流
    val filteredRides = rides.filter(r => GeoUtils.isInNYC(r.startLon, r.startLat) && GeoUtils.isInNYC(r.endLon, r.endLat))

    //打印过滤后的数据流
    printOrScalaTest(filteredRides)

    //执行flink应用
    env.execute("Taxi Ride Cleansing")

  }

}

scala写法,需要注意的是

<dependency>
   <groupId>org.apache.flink</groupId>
   <artifactId>flink-streaming-scala_2.12</artifactId>
   <version>1.12.0</version>
   <!--<scope>provided</scope>-->
</dependency>
<dependency>
   <groupId>org.apache.flink</groupId>
   <artifactId>flink-scala_2.12</artifactId>
   <version>1.12.0</version>
</dependency>

依赖的引入,然后需要注意的是scala引入依赖的版本和scala-sdk的版本。具体解决方法:flink中关于scala版本报错的解决办法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值