flink 1.10.1 + kafka实现流数据时间窗口平均数计算(java版本)

1. 在idea创建maven项目并添加依赖

<properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <flink.version>1.10.1</flink.version>
        <log4j.version>1.2.17</log4j.version>
        <slf4j.version>1.7.7</slf4j.version>
        <scala.version>2.11</scala.version>
    </properties>

<dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <!-- Flink 的 Java api -->
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-java</artifactId>
            <version>${flink.version}</version>
            <scope>${project.build.scope}</scope>
        </dependency>
        <!-- Flink Streaming 的 Java api -->
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-streaming-java_${scala.version}</artifactId>
            <version>${flink.version}</version>
            <scope>${project.build.scope}</scope>
        </dependency>
        <!-- Flink 的 Web UI -->
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-runtime-web_${scala.version}</artifactId>
            <version>${flink.version}</version>
            <scope>${project.build.scope}</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-core</artifactId>
            <version>1.10.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-runtime_2.11</artifactId>
            <version>1.10.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-kafka_2.11</artifactId>
            <version>1.10.1</version>
        </dependency>

    </dependencies>

这里的scala版本选择的是2.11,flink-runtime_2.11在idea开发环境运行时,需要添加此依赖。

2. 添加主功能代码

package com.demo;


import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.api.java.tuple.Tuple;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.streaming.api.TimeCharacteristic;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.windowing.WindowFunction;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.api.windowing.windows.TimeWindow;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer;
import org.apache.flink.util.Collector;

import java.util.Properties;

public class FlinkWindowAvgKafkaStreaming {

    public static void main(String[] args) throws Exception {
        final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.enableCheckpointing(5000); // 设置启动检查点!!
        env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);

        Properties props = new Properties();
        props.setProperty("bootstrap.servers", "localhost:9092");
        props.setProperty("group.id", "flink-group");

        FlinkKafkaConsumer<String> consumer =
                new FlinkKafkaConsumer<>("flink-topic", new SimpleStringSchema(), props);
        consumer.assignTimestampsAndWatermarks(new MessageWaterEmitter());

        DataStream<Tuple3<String, Long, Long>> keyedStream = env
                .addSource(consumer)
                .flatMap(new MessageSplitter())
                .keyBy(0)
                .timeWindow(Time.seconds(10))
                .apply(new WindowFunction<Tuple2<String, Long>, Tuple3<String, Long, Long>, Tuple, TimeWindow>() {
                    @Override
                    public void apply(Tuple tuple, TimeWindow window, Iterable<Tuple2<String, Long>> input, Collector<Tuple3<String, Long, Long>> out) throws Exception {
                        long sum = 0L;
                        int count = 0;
                        for (Tuple2<String, Long> record: input) {
                            sum += record.f1;
                            count++;
                        }
                        Tuple2<String, Long> temp = input.iterator().next();

                        // 统计数据按三元组形式输出
                        Tuple3<String, Long, Long> result = new Tuple3<String, Long, Long>(temp.f0, sum / count, window.getEnd());

                        out.collect(result);
                    }
                });
        
        keyedStream.print("output");
        env.execute("Flink-Kafka demo");
    }

}

从kafka读取数据,对数据进行转换,对转换后的数据先进行分组,然后进行开窗,在窗口范围内计算平均数,并且输出计算的平均数和窗口结束时间。

其中窗口时间为10秒。

3. kafka的模拟消息

1643685175905,machine-1,5436289024
1643685176920,machine-1,5422505984
1643685177924,machine-1,5431537664
1643685178935,machine-1,5425504256
1643685179940,machine-1,5430718464
1643685180947,machine-1,5437231104
1643685181960,machine-1,5522214912
1643685182965,machine-1,5745750016
1643685183976,machine-1,5746868224

模拟数据可以手动通过输入kafka消息生产者进行生成,也可以结合java maven写入kafka消息demo 进行生成。

4. 辅助代码(MessageWaterEmitter

package com.demo;

import org.apache.flink.streaming.api.functions.AssignerWithPunctuatedWatermarks;
import org.apache.flink.streaming.api.watermark.Watermark;

public class MessageWaterEmitter implements AssignerWithPunctuatedWatermarks<String> {
    //@Nullable
    @Override
    public Watermark checkAndGetNextWatermark(String lastElement, long extractedTimestamp) {
        if (lastElement != null && lastElement.contains(",")) {
            String[] parts = lastElement.split(",");
            return new Watermark(Long.parseLong(parts[0]));
        }
        return null;
    }

    @Override
    public long extractTimestamp(String element, long previousElementTimestamp) {
        if (element != null && element.contains(",")) {
            String[] parts = element.split(",");
            return Long.parseLong(parts[0]);
        }
        return 0L;
    }
}

这里定义了时间watermark(水位线)的获取方式。

5. 辅助代码(MessageSplitter)

package com.demo;

import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.util.Collector;


public class MessageSplitter implements FlatMapFunction<String, Tuple2<String, Long>> {

    @Override
    public void flatMap(String value, Collector<Tuple2<String, Long>> out) throws Exception {
        if (value != null && value.contains(",")) {
            String[] parts = value.split(",");
            out.collect(new Tuple2<>(parts[1], Long.parseLong(parts[2])));
        }
    }
}

6. 运行程序,输出结果

 可以看出每隔10秒,就有一组窗口平均数输出。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flink一个开源的处理框架,而Kafka一个分布式消息队列系统。在Flink中使用KafkaJava API可以实现Kafka中的数据作为输入源或将处理结果输出到Kafka中。 在Flink中使用Kafka Java API的步骤通常如下: 1. 引入Kafka的依赖:首先需要将KafkaJava API的依赖添加到Flink的工程中。 2. 创建Kafka消费者:使用KafkaJava API创建一个消费者实例,可以指定消费者的一些配置如Kafka的地址、消费者组ID等。通过调用消费者的`assign()`方法或`subscribe()`方法来指定要消费的Kafka主题。 3. 创建Flink的DataStream:使用Flink的DataStream API实例化一个用于接收Kafka数据的DataStream对象。可以使用`addSource()`方法来将Kafka消费者作为数据源。可以在创建DataStream时指定Kafka消息的反序列化方式、数据类型等。 4. 执行数据处理逻辑:可以在DataStream上应用各种Flink的算子,如map、filter、reduce等,对Kafka中的数据进行处理。 5. 创建Kafka生产者:使用KafkaJava API创建一个生产者实例,可以指定生产者的一些配置。通过调用生产者的`send()`方法将处理后的结果数据发送到Kafka中。 6. 提交任务并启动Flink作业:将处理逻辑应用到Flink的任务上,并将任务提交给Flink集群进行执行。 通过以上步骤,就可以在Flink中使用KafkaJava API进行数据的输入和输出。这种方式将Kafka作为Flink一个数据源或数据目的,使得数据可以在处理中被实时地处理和分析。同时,由于Kafka的分布式特性,也可以保证数据的可靠性和高吞吐量。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值