Kafka设计解析(十八)Kafka与Flink集成
转载自 huxihx,原文链接 Kafka与Flink集成
Apache Flink是新一代的分布式流式数据处理框架,它统一的处理引擎既可以处理批数据(batch data)也可以处理流式数据(streaming data)。在实际场景中,Flink利用Apache Kafka作为上下游的输入输出十分常见,本文将给出一个可运行的实际例子来集成两者。
目录
一、目标
二、环境准备
三、创建Flink Streaming工程
四、增加kafka和kafka-connector依赖
五、启动Flink环境(本例使用local测试环境)
六、启动Kafka单节点集群
七、代码开发
八、部署Flink jar包
1. 打包Flink jar包
2. 部署jar包
3. 运行KafkaProducerTest
一、目标
本例模拟中将集成Kafka与Flink:Flink实时从Kafka中获取消息,每隔10秒去统计机器当前可用的内存数并将结果写入到本地文件中。
二、环境准备
- Apache Kafka 0.11.0.0
- Apache Flink 1.3.1
- Gradle 3.5 (版本号不是强要求)
本例运行在Windows环境,但可以很容易地移植到其他平台上。
三、创建Flink Streaming工程
本例使用Intellij IDEA作为项目开发的IDE。首先创建Gradle project,group为'huxihx.flink.demo',artifact id为‘flink-kafka-demo’,version为‘1.0-SNAPSHOT’。整个项目结构如图所示:

四、增加kafka和kafka-connector依赖
增加下列gradle依赖:
compile group: 'org.apache.flink', name: 'flink-connector-kafka-0.10_2.11', version: '1.3.1'
compile group: 'org.apache.flink', name: 'flink-streaming-java_2.11', version: '1.3.1'
compile group: 'org.apache.kafka', name: 'kafka-clients', version: '0.11.0.0'
设置gradle打包依赖
jar {
manifest {
attributes(
"Manifest-Version": 1.0,
"Main-Class": "huxihx.KafkaMessageStreaming")
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
into('assets') {
from 'assets'
}
}
五、启动Flink环境(本例使用local测试环境)
F:\SourceCode\flink-1.3.1
> bin\start-local.bat
Starting Flink job manager. Webinterface by default on http://localhost:8081/.
Don't close this batch window. Stop job manager by pressing Ctrl+C.
六、启动Kafka单节点集群
启动Zookeeper:
cd F:\SourceCode\zookeeper
> bin\zkServer.cmd
启动Kafka broker:
> cd F:\SourceCode\kafka_1
> set JMX_PORT=9999
> bin\windows\kafka-server-start.bat F:\\SourceCode\\configs\\server.properties
七、代码开发
代码主要由两部分组成:
- MessageSplitter类、MessageWaterEmitter类和KafkaMessageStreaming类:Flink streaming实时处理Kafka消息类
- KafkaProducerTest类和MemoryUsageExtrator类:构建Kafka测试消息
本例中,Kafka消息格式固定为:时间戳,主机名,当前可用内存数。其中主机名固定设置为machine-1,而时间戳和当前可用内存数都是动态获取。由于本例只会启动一个Kafka producer来模拟单台机器发来的消息,因此在最终的统计结果中只会统计machine-1这一台机器的内存。下面我们先来看flink部分的代码实现。
MessageSplitter类(将获取到的每条Kafka消息根据“,”分割取出其中的主机名和内存数信息)
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])));
}
}
}
MessageWaterEmitter类(根据Kafka消息确定Flink的水位)
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;
}
}
KafkaMessageStreaming类(Flink入口类,封装了对于Kafka消息的处理逻辑。本例每10秒统计一次结果并写入到本地文件)
public class KafkaMessageStreaming {
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");
FlinkKafkaConsumer010<String> consumer =
new FlinkKafkaConsumer010<>(args[0], new SimpleStringSchema(), props);
consumer.assignTimestampsAndWatermarks(new MessageWaterEmitter());
DataStream<Tuple2<String, Long>> keyedStream = env
.addSource(consumer)
.flatMap(new MessageSplitter())
.keyBy(0)
.timeWindow(Time.seconds(10))
.apply(new WindowFunction<Tuple2<String, Long>, Tuple2<String, Long>, Tuple, TimeWindow>() {
@Override
public void apply(Tuple tuple, TimeWindow window, Iterable<Tuple2<String, Long>> input, Collector<Tuple2<String, Long>> out) throws Exception {
long sum = 0L;
int count = 0;
for (Tuple2<String, Long> record: input) {
sum += record.f1;
count++;
}
Tuple2<String, Long> result = input.iterator().next();
result.f1 = sum / count;
out.collect(result);
}
});
keyedStream.writeAsText(args[1]);
env.execute("Flink-Kafka demo");
}
}
实现了这些代码之后我们已然可以打包进行部署了,不过在其之前我们先看下Kafka producer测试类的实现——该类每1秒发送一条符合上面格式的Kafka消息供下游Flink集群消费。
MemoryUsageExtrator类(很简单的工具类,提取当前可用内存字节数)
public class MemoryUsageExtrator {
private static OperatingSystemMXBean mxBean =
(OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
/**
* Get current free memory size in bytes
* @return free RAM size
*/
public static long currentFreeMemorySizeInBytes() {
return mxBean.getFreePhysicalMemorySize();
}
}
KafkaProducerTest类(发送Kafka消息)
public class KafkaProducerTest {
public static void main(String[] args) throws Exception {
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("acks", "all");
props.put("retries", 0);
props.put("batch.size", 16384);
props.put("linger.ms", 1);
props.put("buffer.memory", 33554432);
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
Producer<String, String> producer = new KafkaProducer<>(props);
int totalMessageCount = 10000;
for (int i = 0; i < totalMessageCount; i++) {
String value = String.format("%d,%s,%d", System.currentTimeMillis(), "machine-1", currentMemSize());
producer.send(new ProducerRecord<>("test", value), new Callback() {
@Override
public void onCompletion(RecordMetadata metadata, Exception exception) {
if (exception != null) {
System.out.println("Failed to send message with exception " + exception);
}
}
});
Thread.sleep(1000L);
}
producer.close();
}
private static long currentMemSize() {
return MemoryUsageExtrator.currentFreeMemorySizeInBytes();
}
}
八、部署Flink jar包
1. 打包Flink jar包
> cd flink-kafka-demo
> gradle clean build
生成的jar包在项目目录下的build/libs/下,本例中是flink-kafka-demo-1.0-SNAPSHOT.jar
2. 部署jar包
> bin\flink.bat run -c huxihx.KafkaMessageStreaming F:\\Projects\\flink-kafka-demo\\build\\libs\\flink-kafka-demo-1.0-SNAPSHOT.jar test F:\\temp\result.txt
KafkaMessageStreaming类接收两个命令行参数,第一个是Kafka topic名字,第二个是输出文件路径
部署成功之后,可以在Flink控制台(本例中是http://localhost:8081/)中看到job已成功部署,如下图所示:

3. 运行KafkaProducerTest
运行Kafka producer,给Flink job创建输入数据,然后启动一个终端,监控输出文件的变化,
> cd F:\temp
> tail -f result.txt
(machine-1,3942129078)
(machine-1,3934864179)
(machine-1,4044071321)
(machine-1,4091437056)
(machine-1,3925701836)
(machine-1,3753678438)
(machine-1,3746314649)
......
可以看到,Flink每隔10s就会保存一条新的统计记录到result.txt文件中,该记录会统计主机名为machine-1的机器在过去10s的平均可用内存字节数。
总结
本文给出了一个可运行的Flink + Kafka的项目配置及代码实现。值得注意的是,上面例子中用到的Flink Kafka connector使用了Kafka新版本consumer的API,因此不再需要连接Zookeeper信息。
Kafka设计解析(十八)Kafka与Flink集成的更多相关文章
- Kafka设计解析(八)- Exactly Once语义与事务机制原理
原创文章,首发自作者个人博客,转载请务必将下面这段话置于文章开头处. 本文转发自技术世界,原文链接 http://www.jasongj.com/kafka/transaction/ 写在前面的话 本 ...
- Kafka设计解析(八)Exactly Once语义与事务机制原理
转载自 技术世界,原文链接 Kafka设计解析(八)- Exactly Once语义与事务机制原理 本文介绍了Kafka实现事务性的几个阶段——正好一次语义与原子操作.之后详细分析了Kafka事务机制 ...
- Kafka设计解析
Kafka剖析(一):Kafka背景及架构介绍 Kafka设计解析(二):Kafka High Availability (上) Kafka设计解析(三):Kafka High Availabilit ...
- Kafka设计解析(十三)Kafka消费组(consumer group)
转载自 huxihx,原文链接 Kafka消费组(consumer group) 一直以来都想写一点关于kafka consumer的东西,特别是关于新版consumer的中文资料很少.最近Kafka ...
- Kafka设计解析(五)- Kafka性能测试方法及Benchmark报告
本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/12/31/KafkaColumn5_kafka_benchmark 摘要 本文主要介绍了如何利用 ...
- 揭秘Kafka高性能架构之道 - Kafka设计解析(六)
原创文章,同步首发自作者个人博客.转载请务必在文章开头处以超链接形式注明出处http://www.jasongj.com/kafka/high_throughput/ 摘要 上一篇文章<Kafk ...
- 流式处理的新贵 Kafka Stream - Kafka设计解析(七)
原创文章,转载请务必将下面这段话置于文章开头处. 本文转发自技术世界,原文链接 http://www.jasongj.com/kafka/kafka_stream/ Kafka Stream背景 Ka ...
- Kafka设计解析(六)- Kafka高性能架构之道
本文从宏观架构层面和微观实现层面分析了Kafka如何实现高性能.包含Kafka如何利用Partition实现并行处理和提供水平扩展能力,如何通过ISR实现可用性和数据一致性的动态平衡,如何使用NIO和 ...
- Kafka设计解析(七)- Kafka Stream
本文介绍了Kafka Stream的背景,如Kafka Stream是什么,什么是流式计算,以及为什么要有Kafka Stream.接着介绍了Kafka Stream的整体架构,并行模型,状态存储,以 ...
- [Big Data - Kafka] Kafka设计解析(五):Kafka Benchmark
性能测试及集群监控工具 Kafka提供了非常多有用的工具,如Kafka设计解析(三)- Kafka High Availability (下)中提到的运维类工具——Partition Reassign ...
随机推荐
- [HNOI2004]宠物收养场
fhq treap 开俩哨兵节点,然后插入.删除.前驱.后继,统计即可 #include"cstdio" #include"cstring" #include& ...
- js中list 和 map还有string的部分操作
1.创建list或者数组 var list = []; list中添加元素:list.push("hello"); 如果没有先定义为数组类型不能使用 push方法 判断list ...
- 在技术胖博客上学习ES6遇到的坑和想法
第一节:ES6的开发环境搭建 坑1:全局安装babel-cli已经不被官方推荐,改为局部安装(cnpm install babel-cli --save-dev): 坑2:babel src/inde ...
- Ubuntu16安装GPU版本TensorFlow(个人笔记本电脑)
想着开始学习tf了怎么能不用GPU,网上查了一下发现GeForce GTX确实支持GPU运算,所以就尝试部署了一下,在这里记录一下,避免大家少走弯路. 使用个人笔记本电脑thinkpadE570,内存 ...
- LeetCode 题解之Plus One
1.题目描述 2.题目分析 从后向前做加法,等于10则进位,否则直接加1 ,返回 digits; 3.代码 vector<int> plusOne(vector<int>&am ...
- RHEL7系统管理之网络管理
1. RHEL7的网络介绍 在RHEL7中, NetworkManager 提供的默认联网服务是一个动态网络控制和配置守护进程, 支持ifcfg类型的配置文件. NetworkManager 可用于连 ...
- Oracle案例12——NBU Oracle恢复
最近在做NBU ORACLE备份的恢复测试,执行恢复时报错ORA-27211: Failed to load Media Management Library,具体处理过程如下:一.错误信息 执行命令 ...
- 如何通过rman的增量备份恢复dataguard中standby端的数据
很多正在使用dataguard的客户,都会遇到一个棘手的问题: 在备份端与主库同步的过程中由于网络原因或磁盘问题导致一个或多个归档日志丢失,进而dataguard同步无法继续.很多客户都选择了重新全库 ...
- Python读写oracle数据库
最近项目中需要用到Python调用oracle实现读写操作,踩过很多坑,历尽艰辛终于实现了.性能怎样先不说,有方法后面再调优嘛.现在把代码和注意点记录一下. 1. 所需Python工具库 cx_Ora ...
- windows:nginx配置http、https反向代理
一.下载 Windows 版本的 nginx nnginx下载:http://nginx.org/en/download.html 推荐稳定版本.下载完成后,解压得到 nginx-1.14.0 ,我把 ...