Flink自定义数据源

自定义数据源DataSource

前言:

  • DataStream API介绍
    ​Flink 中的 DataStream 程序是对数据流(例如过滤、更新状态、定义窗口、聚合)进行转换的常规程序。数据流的起始是从各种源(例如消息队列、套接字流、文件)创建的。结果通过sink返回,例如可以将数据写入文件或标准输出(例如命令行终端)。Flink 程序可以在各种上下文中运行,可以独立运行,也可以嵌入到其它程序中。任务执行可以运行在本地 JVM 中,也可以运行在多台机器的集群上。

​ 基于 DataStream 派生新的流,并使用 map、filter 等 API 方法把 DataStream 和派生的流连接在一起。
在这里插入图片描述

  • Flink程序剖析:
  1. 获取一个执行环境(execution environment)

  2. 加载/创建初始数据;

  3. 指定数据相关的转换;

  4. 指定计算结果的存储位置;

  5. 触发程序执行

模拟传感器读取的温度

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

        DataStream<SensorReading> dataStream = env.addSource(new MySensorSource());

        dataStream.print();
        env.execute();
    }
    private static class MySensorSource implements SourceFunction<SensorReading> {
        //定义一个标识位,用来控制数据的产生
        private boolean running = true;
        @Override
        public void run(SourceContext<SensorReading> ctx) throws Exception {
            //定义一个随机数发生器
            Random random = new Random();

            //设置10个传感器的初始温度
            HashMap<String, Double> sensorTempMap = new HashMap<>();
            for (int i = 0; i < 10; i++) {
                sensorTempMap.put("sensor_"+(i+1), 60 + random.nextGaussian()*20);
            }

            while(running){
                for(String sensorID : sensorTempMap.keySet()){
                    //在当前温度基础上随机波动
                    Double newtemp = sensorTempMap.get(sensorID)+ random.nextGaussian();
                    sensorTempMap.put(sensorID,newtemp);

                    ctx.collect(new SensorReading(sensorID,System.currentTimeMillis(),newtemp));
                }
              //控制输出频率
                Thread.sleep(1000L);
            }
        }

        @Override
        public void cancel() {
            running = false;
        }
    }

分析

添加数据源的方法,需要传入一个function,SourceFunction是定义的一个接口,传入的function需要实现该接口

public <OUT> DataStreamSource<OUT> addSource(SourceFunction<OUT> function) {
		return addSource(function, "Custom Source");
	}

因此,自定义一个类MySensorSource实现SourceFunction接口,而最后输出的数据是自定义的SensorReading类,所以SourceFunction的泛型是<SensorReading>。之后重写runcancel方法
在run方法中,读取hashmap中的10个数据,最后收集的结果为ID,时间戳,温度

有一行代码最为关键

 ctx.collect(new SensorReading(sensorID,System.currentTimeMillis(),newtemp));

debug开始:
进入这个函数,发现跳到了NonTimestampContext类里的collect方法,因此可以推断出调用run函数的时候,传入了NonTimestampContext类的实例对象

public void run(SourceContext<SensorReading> ctx)

回到调用run函数之前,如下图
在这里插入图片描述
果然,在调用run函数之前,ctx通过getSourceContext函数变成了NonTimestampContext类的实例对象,调用run函数时传入了NonTimestampContext类对象,因此在run函数里的ctx变成了NonTimestampContext类的实例对象
在这里插入图片描述
打印出来的结果如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值