【Flink】【第五章 流处理API】Function接口 & RichFunction

  • Flink在使用各种不同算子的同时,为了能更细粒度的控制数据和操作数据,给开发者提供了对现有函数功能进行扩展的能力,这就是函数类(FunctionClasses)。也可以简单地理解为UDF函数(用户自定义函数)

  • Flink每一个算子的参数都可以使用lambda表达式函数类两种的方式,其中如果使用函数类作为参数的话,需要让自定义函数继承指定的父类或实现特定的接口。

函数类(Function Classes)

  • 函数类官方称之为:user-defined function
  • udf 是接口,每种udf提供了自己独特的方法用于处理流中的每一条数据
  • udf就是算子中的参数;各种算子对应各种udf

(1)所有函数类接口的父接口都是Function,是一个空的接口,实现了序列化。
在这里插入图片描述

在这里插入图片描述

匿名函数(Lambda Functions)

就是Java8 Lambda表达式写法

DataStream<String> tweets = env.readTextFile("INPUT_FILE");

DataStream<String> flinkTweets = tweets.filter( tweet -> tweet.contains("flink") );

富函数(Rich Functions)☆

RichXxxFunction

  • RichXxxFunction是抽象类
  • 继承了AbstractRichFunction抽象类,获取了RichFunction接口提供的功能;
  • 实现了XxxFunction接口,获取了独特的处理数据的功能
    在这里插入图片描述

Flink中的所有UserDefineFunction都有”富函数”版本,比如:

  • MapFunction =>RichMapFunction
  • FlatMapFunction => RichFlatMapFunction
  • FilterFunction => RichFilterFunction

RichFunction

在这里插入图片描述
RichFunction是一个基本接口,也继承Function接口,此接口提供了两个额外功能:

  • 获取function的生命周期的方法
  • 获取function运行时上下文的方法
    在这里插入图片描述

Rich-UDF的两个额外功能都是由RichFunction接口提供的,但是Rich-UDF并不直接继承此接口,flink提供了默认实现,放在AbstractRichFunction抽象类中


(1)两个生命周期方法


	/**
	 * Initialization method for the function. It is called before the actual working methods
	 * (like <i>map</i> or <i>join</i>) and thus suitable for one time setup work. For functions that
	 * are part of an iteration, this method will be invoked at the beginning of each iteration superstep.
	 *
	 * <p>The configuration object passed to the function can be used for configuration and initialization.
	 * The configuration contains all parameters that were configured on the function in the program
	 * composition.
	 *
	 * <pre>{@code
	 * public class MyFilter extends RichFilterFunction<String> {
	 *
	 *     private String searchString;
	 *
	 *     public void open(Configuration parameters) {
	 *         this.searchString = parameters.getString("foo");
	 *     }
	 *
	 *     public boolean filter(String value) {
	 *         return value.equals(searchString);
	 *     }
	 * }
	 * }</pre>
	 *
	 * <p>By default, this method does nothing.
	 *
	 * @param parameters The configuration containing the parameters attached to the contract.
	 *
	 * @throws Exception Implementations may forward exceptions, which are caught by the runtime. When the
	 *                   runtime catches an exception, it aborts the task and lets the fail-over logic
	 *                   decide whether to retry the task execution.
	 *
	 * @see org.apache.flink.configuration.Configuration
	 */
	void open(Configuration parameters) throws Exception;

	/**
	 * Tear-down method for the user code. It is called after the last call to the main working methods
	 * (e.g. <i>map</i> or <i>join</i>). For functions that  are part of an iteration, this method will
	 * be invoked after each iteration superstep.
	 *
	 * <p>This method can be used for clean up work.
	 *
	 * @throws Exception Implementations may forward exceptions, which are caught by the runtime. When the
	 *                   runtime catches an exception, it aborts the task and lets the fail-over logic
	 *                   decide whether to retry the task execution.
	 */
	void close() throws Exception;

1.open()方法:rich function的初始化方法,当一个算子例如map或者filter被调用之前open()会被调用。
2.close()方法:是生命周期中的最后一个调用的方法,做一些清理工作。


(2)生命周期方法的特点

  • 生命周期方法提供了一种全局的视角,而非局限于单个元素;
  • 生命周期方法是基于并行度的,并非整个dataStream只调用一次,而是一个并行度调用一次;
  • 生命周期方法可以提供一些建立在DataStream上的功能,比如获取第三方框架的连接

演示:生命周期方法是在并行度的基础上

public static class MyMapFunction extends RichMapFunction<SensorReading, Tuple2<Integer, String>> {
    @Override
    public Tuple2<Integer, String> map(SensorReading value) throws Exception {
        return new Tuple2<>(getRuntimeContext().getIndexOfThisSubtask(), value.getId());
    }

    @Override
    public void open(Configuration parameters) throws Exception {
        System.out.println("my map open");
        // 以下可以做一些初始化工作,例如建立一个和HDFS的连接
    }

    @Override
    public void close() throws Exception {
        System.out.println("my map close");
        // 以下做一些清理工作,例如断开和HDFS的连接
    }
}
    @Test
    public void map() throws Exception {
        source = env.readTextFile("D:\\IdeaProjects\\bigdata\\flink\\src\\main\\resources\\sensort.txt");
        SingleOutputStreamOperator<SensorReading> map = source.map(new MyMapFunction());

        SingleOutputStreamOperator<Tuple2<Integer, String>> map1 = map.map(new MyMapRichFunction());

        map1.print();

        env.execute();

        //my map open
        //my map open
        //my map open
        //my map open
        //3> (2,sensor_1)
        //2> (1,sensor_1)
        //1> (0,sensor_7)
        //4> (3,sensor_1)
        //my map close
        //3> (2,sensor_6)
        //my map close
        //my map close
        //1> (0,sensor_10)
        //my map close
    }

可以看到四个并行度,生命周期方法执行了四次;

(2)获取运行时上下文

getRuntimeContext()方法:获取函数的运行时上下文RuntimeContext,从中可以获取函数的信息:例如函数执行的并行度,任务的名字,以及状态编程(算子的状态)

此部分在状态编程中做介绍;

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Flink是一个开源的分布式处理框架,它提供了强大的数据处理能力。在处理股票价格数据时,Flink可以帮助我们实现实时的数据分析、计算和预测。 首先,我们可以使用Flink连接并读取股票价格数据,这可以通过从消息队列、Kafka主题或其他数据源中消费数据来实现。然后,我们可以应用Flink提供的数据转换和操作函数来进行数据处理,例如过滤、映射、聚合等。我们可以根据股票价格的要求,自定义相应的处理逻辑。 其次,Flink还支持窗口操作,这对于股票价格数据处理非常有用。我们可以定义滚动窗口、滑动窗口或会话窗口,以便对一定时间范围内的股票价格数据进行计算和分析。例如,我们可以计算某个窗口内的平均股票价格、最高价或最低价等。 另外,Flink还提供了状态管理功能,这对于股票价格数据处理非常重要。我们可以在处理过程中维护和更新状态,以便实时跟踪和分析股票价格的变化。例如,我们可以记录某只股票的历史价格、成交量等。 最后,Flink还支持与外部系统的连接和集成,例如数据库、存储、API等。这可以让我们将股票价格数据与其他数据源和服务进行集成,以便获取更全面的信息和进行更高级的分析。例如,我们可以将股票价格数据与交易量、新闻事件等数据进行关联分析,以便预测股票市场的趋势。 总而言之,Flink是一个非常适合处理股票价格数据的框架。它提供了灵活且高效的数据处理能力,可以实现实时的数据分析、计算和预测。无论是数据提取、转换、窗口操作还是状态管理,Flink都能满足股票价格数据处理的需求,并且提供了与外部系统的连接和集成能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值