Flink流处理api之source

448 阅读3分钟

欢迎关注我的个人博客学习更多知识

flink流处理基础框架

类比于storm 和 spark flink也是有执行环境 下面写出最小框架

public class SourceTest {
public static void main(String[] args) throws Exception{
// 创建执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 导入数据
DataStreamSource<String> stream = env.readTextFile("");
//处理数据
stream.print();
// 执行
env.execute();
}
}

StreamExecutionEnvironment.getExecutionEnvironment(); 函数可以根据情况自动返回到本地执行环境活或者是集群执行环境 当然也可以通过函数设置

返回本地执行环境,需要在调用时指定默认的并行度

StreamExecutionEnvironment env = StreamExecutionEnvironment.createLocalEnvironment(1)

返回集群执行环境,将Jar 提交到远程服务器。需要在调用时指定JobManager 的IP 和端口号,并指定要在集群中运行的Jar 包

StreamExecutionEnvironment env =ExecutionEnvironment.createRemoteEnvironment("jobmanage-hostname",
6123,"YOURPATH//wordcount.jar")

Source

从集合中读取数据(有限流)

首先定义数据源样例类

//对于数据流中的数据类型 我们通常使用POJP(java)和 case class(Scala)来定义一个数据类型类

//其中对于POJO方法
// 当我们要用keyby进行分组时候
// POJO类的定义必须满足一下条件
//1.字段名必须声明为public的;
//2.必须有默认的无参构造器;
//3.所有构造器必须声明为public的
// 定义样例类 传感器 id 时间戳 温度
 class SensorReading {
    // 传感器 id
    private String id;
    // 传感器时间戳
    private Long timestamp;
    // 传感器温度
    private Double temperature;


    public SensorReading(String id, Long timestamp, Double temperature) {
        this.id = id;
        this.timestamp = timestamp;
        this.temperature = temperature;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(Long timestamp) {
        this.timestamp = timestamp;
    }

    public Double getTemperature() {
        return temperature;
    }

    public void setTemperature(Double temperature) {
        this.temperature = temperature;
    }

    @Override
    public String toString() {
        return "SensorReading{" +
                "id='" + id + '\'' +
                ", timestamp=" + timestamp +
                ", temperature=" + temperature +
                '}';
    }
}

编写主逻辑代码

public class SourceTest {
    public static void main(String[] args) throws Exception{
        //创建执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        // 导入集合数据   这个是个有界数据流
        DataStreamSource<SensorReading> stream1 = env.fromCollection(Arrays.asList(
                new SensorReading("sensor_1", 1547718199L, 35.8),
                new SensorReading("sensor_6", 1547718201L, 15.4),
                new SensorReading("sensor_7", 1547718202L, 6.7),
                new SensorReading("sensor_10", 1547718205L, 38.1),
                new SensorReading("sensor_15", 1547716505L, 39.1),
                new SensorReading("sensor_18", 1547718685L, 78.1)
                )
        );
        // 打印数据
        stream1.print(); //并行度默认cpu核心数
        // 执行
        env.execute("source test");
    }
}

执行看看 等待几秒后 image.png

可以看出 顺序是打乱了的

从文件中读取数据

这个就很简单了 核心代码

DataStreamSource stream2 = env.readTextFile("");

以kafka 消息队列的数据作为来源(重点)

引入Kafka连接器的依赖

<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-kafka-0.11_2.12</artifactId>
<version>1.10.1</version>
</dependency>

配置Kafka相关信息

//kafka 配置
        Properties properties = new Properties();
        properties.setProperty("bootstrap.servers", "192.168.216.111:9092,192.168.216.112:9092,192.168.216.113:9092");
        properties.setProperty("group.id", "flink-kafka");
        properties.setProperty("key.deserializer",
                "org.apache.kafka.common.serialization.StringDeserializer");
        properties.setProperty("value.deserializer",
                "org.apache.kafka.common.serialization.StringDeserializer");
        properties.setProperty("auto.offset.reset", "latest");

读取数据

// 读取Kafka topic中的数据
        DataStreamSource<String> stream3 = env.addSource(new FlinkKafkaConsumer011<String>(
                "sensor",
                new SimpleStringSchema(),
                properties
        ));
stream3.print();

flink中的addSource()函数提供了导入数据源方法,其中可以用flink已经定义好的Source(如上文kafka),当然也能自定义Source 下面就开看看如何自定义Source

自定义Source

除了以上的source 数据来源,我们还可以自定义source。需要做的,只是传入 一个SourceFunction 就可以。具体调用如下:

DataStreamSource<String> stream4 = env.addSource(new new CustomSource())

下面定义可以随机生成传感器数据的数据源

public class SourceFromCustom {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        DataStreamSource<SensorReading> inputDataStream = env.addSource(new CustomSource());
        inputDataStream.print();
        env.execute();
    }

    // 继承SourceFunction的富函数RichSourceFunction
    public static class CustomSource implements SourceFunction<SensorReading> {
        boolean running = true;
        @Override
        public void run(SourceContext<SensorReading> sourceContext) throws Exception {

            Random random = new Random();
            // 定义无线循环,不断产生数据,除非被cancel
            while (running) {
                // 每隔 100 秒数据
                for (int i = 0; i < 5; i++) {
                    String id = UUID.randomUUID().toString().substring(0, 8);
                    long timestamp = System.currentTimeMillis();  //获取毫秒时间
                    double temperature = 60 + random.nextGaussian() * 20;  //nextGaussian():返回平均值为0.0,标准差为1.0的下一个伪随机高斯分布双精度数
                    sourceContext.collect(new SensorReading(id, timestamp, temperature));

                    Thread.sleep(100L);
                }

                Thread.sleep(1000L);
            }
        }

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

运行结果如下 image.png

本文转载于我的个人博客Flink流处理api之source 遵循 CC 4.0 BY-SA 版权协议

欢迎交流学习

个人博客

csdn主页