Flink初试——对接Kafka

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
实时计算 Flink 版,1000CU*H 3个月
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
简介: Flink初试——对接Kafka

本篇文章我们用 Flink Kafka Connector对接Kafka,实现一个简单的报警业务。我们暂时不去谈论理论,先上手实现这个简单的需求。

flink-connector-kafka是 flink 内置的Kafka连接器,包含了从topic读取数据的Flink Kafka Consumer 和 向topic写入数据的flink kafka producer,除了基本功能外还提供了基于 checkpoint 机制提供了完美的容错能力。

本文基于flink 1.10.1 和 flink-connector-kafka-0.10_2.11版本,pom如下:

<dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-kafka-0.10_2.11</artifactId>
            <version>1.10.0</versio>
</dependency>

以企业常见的预警业务为例,本文要实现的业务逻辑很简单,当设备上报的油桶余量不足10%时,便生成一个报警,这里我们将报警写入MySQL,以供web业务端展示报警报表。

首先我们用网络数据调试器向网关模拟发送数据,网关会将数据解析后写入kafka


kafka-console-consumer --bootstrap-server cdh1.macro.com:9092,cdh2.macro.com:9092,cdh3.macro.com:9092 --from-beginning --topic fill
{"addTime":1593147840000,"currentAmount":0.3,"devId":"XT365-000170","devStatus":"1","ifOffline":"1","ip":"127.0.0.1","leftTankAmount":5,"realTotalAmount":2377.39,"registerTime":1606658457000,"settingAmount":0.3,"tankCapacity":1000,"totalAmount":2017.9315}
{"addTime":1593147840000,"currentAmount":0.3,"devId":"XT365-000170","devStatus":"1","ifOffline":"1","ip":"127.0.0.1","leftTankAmount":5,"realTotalAmount":2377.69,"registerTime":1606658458000,"settingAmount":0.3,"tankCapacity":1000,"totalAmount":2017.9315}
^C20/11/29 23:26:55 INFO internals.ConsumerCoordinator: [Consumer clientId=consumer-console-consumer-82199-1, groupId=console-consumer-82199] Revoke previously assigned partitions fill-0
20/11/29 23:26:55 INFO internals.AbstractCoordinator: [Consumer clientId=consumer-console-consumer-82199-1, groupId=console-consumer-82199] Member consumer-console-consumer-82199-1-aa5fc2e6-1f06-4714-9d89-fe080a9400e2 sending LeaveGroup request to coordinator cdh2.macro.com:9092 (id: 2147483598 rack: null) due to the consumer is being closed
Processed a total of 1200 messages


可以看到我们已经向kafka生产了1200条数据了

接下来我们写一段代码来消费kafka数据,并将报警结果写入MySQL

import com.alibaba.fastjson.JSONObject;
import com.iiot.bean.InSufficient;
import com.iiot.commCommon.Fill;
import com.iiot.jdbc.MySQLSinks;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.windows.TimeWindow;
import org.apache.flink.streaming.api.windowing.time.Time;
import java.util.List;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer010;
import org.apache.flink.util.Collector;
import org.apache.flink.shaded.guava18.com.google.common.collect.Lists;
import org.apache.flink.streaming.api.functions.windowing.AllWindowFunction;
import java.util.Properties;
public class InSufficientOilAlarms {
    public static void main(String[] args) throws Exception{
        //构建流执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        //kafka
        Properties prop = new Properties();
        prop.put("bootstrap.servers", "cdh1.macro.com:9092,cdh2.macro.com:9092,cdh3.macro.com:9092");
//        prop.put("zookeeper.connect", "localhost:2181");
        prop.put("group.id", "fill6");
        prop.put("key.serializer", "org.apache.kafka.common.serialization.StringDeserializer");
        prop.put("value.serializer", "org.apache.kafka.common.serialization.StringDeserializer");
        prop.put("auto.offset.reset", "earliest");
        DataStreamSource<String> stream = env
                .addSource(new FlinkKafkaConsumer010<String>(
                        "fill",
                        new SimpleStringSchema(), prop)).
                //单线程打印,控制台不乱序,不影响结果
                setParallelism(1);
        //从kafka里读取数据,转换成Person对象
        DataStream<Fill> dataStream = stream.map(value ->
                JSONObject.parseObject(value, Fill.class)
        );
        SingleOutputStreamOperator<InSufficient> result = dataStream.map(new MapFunction<Fill, InSufficient>() {
                           @Override
                           public InSufficient map(Fill fill) throws Exception {
                               InSufficient inSufficient = new InSufficient();
                               Float leftTankAmount = fill.getLeftTankAmount();
                               Float tankCapacity = fill.getTankCapacity();
                               String devCode = fill.getDevId();
                               long timeBegin = fill.getAddTime().getTime();
                               System.out.println("devCode:-------------------------------------------------" + devCode);
                               String alarmType = "";
                               if ((leftTankAmount / tankCapacity) < 0.1 ) {
                                   alarmType = "inSufficientOil";
                                   inSufficient.setDev_code(devCode);
                                   inSufficient.setCreateTime(System.currentTimeMillis());
                                   inSufficient.setTimeBegin(timeBegin);
                                   inSufficient.setAlarmType(alarmType);
                                   inSufficient.setRemainAmount(leftTankAmount);
                               }
                               return inSufficient;
                           }
                       }
        );
        //收集5秒钟的总数
        result.timeWindowAll(Time.seconds(5L)).
                apply(new AllWindowFunction<InSufficient, List<InSufficient>, TimeWindow>() {
                    @Override
                    public void apply(TimeWindow timeWindow, Iterable<InSufficient> iterable, Collector<List<InSufficient>> out) throws Exception {
                        List<InSufficient> inSufficients = Lists.newArrayList(iterable);
                        if(inSufficients.size() > 0) {
                            System.out.println("5秒的总共收到的条数:" + inSufficients.size());
                            out.collect(inSufficients);
                        }
                    }
                })
                //sink 到数据库
                .addSink(new MySQLSinks());
        //打印到控制台
        //.print();
        env.execute("kafka 消费任务开始");
    }
}


将项目打包,传到集群中,用Flink on YARN的方式运行作业

[root@cdh3 bin]# flink run -m yarn-cluster -c com.iiot.alarm.InSufficientOilAlarms /data0/flinkdemo/stream-1.0-SNAPSHOT-jar-with-dependencies.jar 
20/11/30 01:40:15 INFO cli.CliFrontend: --------------------------------------------------------------------------------
20/11/30 01:40:15 INFO cli.CliFrontend:  Starting Command Line Client (Version: 1.10.0-csa1.2.0.0, Rev:04dddd1, Date:29.05.2020 @ 14:54:45 UTC)
20/11/30 01:40:15 INFO cli.CliFrontend:  OS current user: root
20/11/30 01:40:16 INFO cli.CliFrontend:  Current Hadoop/Kerberos user: hdfs
20/11/30 01:40:16 INFO cli.CliFrontend:  JVM: Java HotSpot(TM) 64-Bit Server VM - Oracle Corporation - 1.8/25.171-b11
20/11/30 01:40:16 INFO cli.CliFrontend:  Maximum heap size: 3531 MiBytes
20/11/30 01:40:16 INFO cli.CliFrontend:  JAVA_HOME: /usr/java/latest
20/11/30 01:40:16 INFO cli.CliFrontend:  Hadoop version: 2.7.5
20/11/30 01:40:16 INFO cli.CliFrontend:  JVM Options:
20/11/30 01:40:16 INFO cli.CliFrontend:     -Datlas.conf=/etc/atlas/conf/
20/11/30 01:40:16 INFO cli.CliFrontend:     -Dlog.file=/var/log/flink/flink-root-client-cdh3.macro.com.log
20/11/30 01:40:16 INFO cli.CliFrontend:     -Dlog4j.configuration=file:/etc/flink/conf/log4j-cli.properties
20/11/30 01:40:16 INFO cli.CliFrontend:     -Dlogback.configurationFile=file:/etc/flink/conf/logback.xml
20/11/30 01:40:16 INFO cli.CliFrontend:  Program Arguments:
20/11/30 01:40:16 INFO cli.CliFrontend:     run
20/11/30 01:40:16 INFO cli.CliFrontend:     -m
20/11/30 01:40:16 INFO cli.CliFrontend:     yarn-cluster
20/11/30 01:40:16 INFO cli.CliFrontend:     -c
20/11/30 01:40:16 INFO cli.CliFrontend:     com.iiot.alarm.InSufficientOilAlarms
20/11/30 01:40:16 INFO cli.CliFrontend:     /data0/flinkdemo/stream-1.0-SNAPSHOT-jar-with-dependencies.jar
20/11/30 01:40:51 INFO zookeeper.ZooKeeper: Client environment:java.io.tmpdir=/tmp
20/11/30 01:40:51 INFO zookeeper.ZooKeeper: Client environment:java.compiler=<NA>
20/11/30 01:40:51 INFO zookeeper.ZooKeeper: Client environment:os.name=Linux
20/11/30 01:40:51 INFO zookeeper.ZooKeeper: Client environment:os.arch=amd64
20/11/30 01:40:51 INFO zookeeper.ZooKeeper: Client environment:os.version=3.10.0-327.el7.x86_64
20/11/30 01:40:51 INFO zookeeper.ZooKeeper: Client environment:user.name=root
20/11/30 01:40:51 INFO zookeeper.ZooKeeper: Client environment:user.home=/root
20/11/30 01:40:51 INFO zookeeper.ZooKeeper: Client environment:user.dir=/opt/cloudera/parcels/FLINK-1.10.0-csa1.2.0.0-cdh7.1.1.0-565-3454809/bin
20/11/30 01:40:51 INFO zookeeper.ZooKeeper: Client environment:os.memory.free=134MB
20/11/30 01:40:51 INFO zookeeper.ZooKeeper: Client environment:os.memory.max=3531MB
20/11/30 01:40:51 INFO zookeeper.ZooKeeper: Client environment:os.memory.total=359MB
20/11/30 01:40:51 INFO utils.Compatibility: Using emulated InjectSessionExpiration
20/11/30 01:40:51 INFO imps.CuratorFrameworkImpl: Starting
20/11/30 01:40:51 INFO zookeeper.ZooKeeper: Initiating client connection, connectString=cdh1.macro.com:2181,cdh2.macro.com:2181,cdh3.macro.com:2181 sessionTimeout=60000 watcher=org.apache.flink.shaded.curator.org.apache.curator.ConnectionState@1460c81d
20/11/30 01:40:51 INFO common.X509Util: Setting -D jdk.tls.rejectClientInitiatedRenegotiation=true to disable client-initiated TLS renegotiation
20/11/30 01:40:51 INFO zookeeper.ClientCnxnSocket: jute.maxbuffer value is 4194304 Bytes
20/11/30 01:40:51 INFO zookeeper.ClientCnxn: zookeeper.request.timeout value is 0. feature enabled=
20/11/30 01:40:51 WARN zookeeper.ClientCnxn: SASL configuration failed: javax.security.auth.login.LoginException: No JAAS configuration section named 'Client' was found in specified JAAS configuration file: '/tmp/jaas-8202592158525653501.conf'. Will continue connection to Zookeeper server without SASL authentication, if Zookeeper server allows it.
20/11/30 01:40:51 INFO zookeeper.ClientCnxn: Opening socket connection to server cdh1.macro.com/192.168.0.171:2181
20/11/30 01:40:51 INFO zookeeper.ClientCnxn: Socket connection established, initiating session, client: /192.168.0.208:38183, server: cdh1.macro.com/192.168.0.171:2181
20/11/30 01:40:51 ERROR curator.ConnectionState: Authentication failed
20/11/30 01:40:51 INFO imps.CuratorFrameworkImpl: Default schema
20/11/30 01:40:51 INFO zookeeper.ClientCnxn: Session establishment complete on server cdh1.macro.com/192.168.0.171:2181, sessionid = 0x3008be9995512b4, negotiated timeout = 60000
20/11/30 01:40:51 INFO state.ConnectionStateManager: State change: CONNECTED
20/11/30 01:40:51 INFO imps.EnsembleTracker: New config event received: {server.1=cdh2.macro.com:3181:4181:participant, version=0, server.3=cdh1.macro.com:3181:4181:participant, server.2=cdh3.macro.com:3181:4181:participant}
20/11/30 01:40:51 ERROR imps.EnsembleTracker: Invalid config event received: {server.1=cdh2.macro.com:3181:4181:participant, version=0, server.3=cdh1.macro.com:3181:4181:participant, server.2=cdh3.macro.com:3181:4181:participant}
20/11/30 01:40:51 INFO imps.EnsembleTracker: New config event received: {server.1=cdh2.macro.com:3181:4181:participant, version=0, server.3=cdh1.macro.com:3181:4181:participant, server.2=cdh3.macro.com:3181:4181:participant}
20/11/30 01:40:51 ERROR imps.EnsembleTracker: Invalid config event received: {server.1=cdh2.macro.com:3181:4181:participant, version=0, server.3=cdh1.macro.com:3181:4181:participant, server.2=cdh3.macro.com:3181:4181:participant}
20/11/30 01:40:52 INFO leaderretrieval.ZooKeeperLeaderRetrievalService: Starting ZooKeeperLeaderRetrievalService /leader/rest_server_lock.

可以在YARN作业中看到Flink的做作业一直在运行。

flink dashboard也可以看到作业一直在运行:

进入YARN reourcemanager里面查看作业运行日志:

可以看到MySQL已经插入数据了。


相关文章
消息中间件 存储 传感器
48 0
|
3月前
|
消息中间件 SQL 关系型数据库
Flink CDC + Kafka 加速业务实时化
Flink CDC 是一种支持流批一体的分布式数据集成工具,通过 YAML 配置实现数据传输过程中的路由与转换操作。它已从单一数据源的 CDC 数据流发展为完整的数据同步解决方案,支持 MySQL、Kafka 等多种数据源和目标端(如 Delta Lake、Iceberg)。其核心功能包括多样化数据输入链路、Schema Evolution、Transform 和 Routing 模块,以及丰富的监控指标。相比传统 SQL 和 DataStream 作业,Flink CDC 提供更灵活的 Schema 变更控制和原始 binlog 同步能力。
|
4月前
|
消息中间件 运维 Kafka
直播预告|Kafka+Flink 双引擎实战:手把手带你搭建分布式实时分析平台!
直播预告|Kafka+Flink 双引擎实战:手把手带你搭建分布式实时分析平台!
171 11
|
4月前
|
消息中间件 运维 Kafka
直播预告|Kafka+Flink双引擎实战:手把手带你搭建分布式实时分析平台!
在数字化转型中,企业亟需从海量数据中快速提取价值并转化为业务增长动力。5月15日19:00-21:00,阿里云三位技术专家将讲解Kafka与Flink的强强联合方案,帮助企业零门槛构建分布式实时分析平台。此组合广泛应用于实时风控、用户行为追踪等场景,具备高吞吐、弹性扩缩容及亚秒级响应优势。直播适合初学者、开发者和数据工程师,参与还有机会领取定制好礼!扫描海报二维码或点击链接预约直播:[https://developer.aliyun.com/live/255088](https://developer.aliyun.com/live/255088)
343 35
直播预告|Kafka+Flink双引擎实战:手把手带你搭建分布式实时分析平台!
|
8月前
|
消息中间件 存储 缓存
kafka 的数据是放在磁盘上还是内存上,为什么速度会快?
Kafka的数据存储机制通过将数据同时写入磁盘和内存,确保高吞吐量与持久性。其日志文件按主题和分区组织,使用预写日志(WAL)保证数据持久性,并借助操作系统的页缓存加速读取。Kafka采用顺序I/O、零拷贝技术和批量处理优化性能,支持分区分段以实现并行处理。示例代码展示了如何使用KafkaProducer发送消息。
|
11月前
|
消息中间件 存储 运维
为什么说Kafka还不是完美的实时数据通道
【10月更文挑战第19天】Kafka 虽然作为数据通道被广泛应用,但在实时性、数据一致性、性能及管理方面存在局限。数据延迟受消息堆积和分区再平衡影响;数据一致性难以达到恰好一次;性能瓶颈在于网络和磁盘I/O;管理复杂性涉及集群配置与版本升级。
392 1
|
11月前
|
消息中间件 Java Kafka
Flink-04 Flink Java 3分钟上手 FlinkKafkaConsumer消费Kafka数据 进行计算SingleOutputStreamOperatorDataStreamSource
Flink-04 Flink Java 3分钟上手 FlinkKafkaConsumer消费Kafka数据 进行计算SingleOutputStreamOperatorDataStreamSource
271 1
|
vr&ar 图形学 开发者
步入未来科技前沿:全方位解读Unity在VR/AR开发中的应用技巧,带你轻松打造震撼人心的沉浸式虚拟现实与增强现实体验——附详细示例代码与实战指南
【8月更文挑战第31天】虚拟现实(VR)和增强现实(AR)技术正深刻改变生活,从教育、娱乐到医疗、工业,应用广泛。Unity作为强大的游戏开发引擎,适用于构建高质量的VR/AR应用,支持Oculus Rift、HTC Vive、Microsoft HoloLens、ARKit和ARCore等平台。本文将介绍如何使用Unity创建沉浸式虚拟体验,包括设置项目、添加相机、处理用户输入等,并通过具体示例代码展示实现过程。无论是完全沉浸式的VR体验,还是将数字内容叠加到现实世界的AR应用,Unity均提供了所需的一切工具。
622 0
|
消息中间件 存储 关系型数据库
实时计算 Flink版产品使用问题之如何使用Kafka Connector将数据写入到Kafka
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
消息中间件 监控 Kafka
实时计算 Flink版产品使用问题之处理Kafka数据顺序时,怎么确保事件的顺序性
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。

热门文章

最新文章