Flink对接KafKa消费分词统计Demo
1. 环境准备
环境需要:
- KafKa_2.12(1.0.0以上)
- Java_1.8(java 8/11)
- Flink
1.1 KafKa
通过Apache KafKa官网下载KafKa,目前版本最新为KafKa_2.12-2.60,KafKa安装包内已包含Zookeeper
下载完成后在本地解压可以看到文件夹KafKa_2.12-2.60
KafKa目录下有
- bin
- windows:存放了windwos环境下KafKa和Zookeeper的启动脚本
- config:配置文件
- libs:各种jar包
- logs:KafKa server的运行日志
- site-docs:API文档
1.1.1 KafKa启动
windows下启动KafKa,进入KafKa_2.12-2.60binwindows目录,打开cmd
- 启动Zookeeper
zookeeper-server-start.bat ....configzookeeper.properties
- 启动KafKa server
kafka-server-start.bat ....configserver.properties
Zookeeper和KafKa启动成功后,会有两个cmd窗口
1.1.2 测试KafKa
打开cmd
- 创建一个名为“test”的Topic
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
- 查看创建的Topic列表,可以看到test topic创建成功
kafka-topics.bat --list --zookeeper localhost:2181
现在我们可以模拟一个Producer和Consumer来测试KafKa的生成消费过程
- 创建一个生产者Producer,生产test主题的消息
kafka-console-producer.bat --broker-list localhost:9092 --topic test
- 创建一个消费者Consumer,消费test主题消息
kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic test --from-beginning
windows环境下生产者和消费者需要在两个不同的cmd窗口中
生产者启动后的窗口可以看到如下,可以向生产者窗口发送消息
在消费者窗口可以看到消息的接收表示成功
我们可以看到消费者窗口还有很多其他消息,这是因为启动消费者的时候对偏移量的设置,通过偏移量可以设置消费者从Topic的什么位置开始消费,由于此处我们选择的是--from-beginning,因此每次都是从test主题的头部开始消费,消费者会消费test topic下的所有消息。
2. Flink对接KafKa
2.1 分词统计Demo
通过windows下的测试,基本了解KafKa生产和消费的操作过程,那么如何通过Flink框架去消费KafKa中的消息呢,以下我们提供一个测试Demo,通过消费KafKa中的消息,并经过Flink算子处理,进行分词统计。
- IDEA下新建一个Maven工程
- 导入pom.xml依赖,为了版本的稳定我们没有选择引入最新的版本
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>FlinkTest</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients_2.11</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_2.11</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-java</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-kafka-0.8_2.11</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
- 创建一个KafKa消费类 KafkaConsumer.java
package KafKaToFlink;
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.streaming.util.serialization.SimpleStringSchema;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer08;
import org.apache.flink.util.Collector;
import java.util.Properties;
public class KafkaConsumer {
public static final class LineSplitter implements FlatMapFunction<String, Tuple2<String, Integer>> {
private static final long serialVersionUID = 1L;
@Override
public void flatMap(String value, Collector<Tuple2<String, Integer>> collector) throws Exception {
//按空格分词
String[] words = value.split(" ");
//遍历所有word,包成二元组输出
for(String word : words) {
collector.collect(new Tuple2<>(word, 1));
}
}
}
public static void main(String[] args) throws Exception {
//创建Flink执行环境
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//设置监控数据流的时间间隔
env.enableCheckpointing(1000);
//配置KafKa和Zookeeper的ip和端口
Properties properties = new Properties();
properties.setProperty("bootstrap.servers", "localhost:9092");
properties.setProperty("zookeeper.connect", "localhost:2181");
properties.setProperty("group.id", "test");
//将kafka和zookeeper配置信息加载到Flink的执行环境当中StreamExecutionEnvironment
FlinkKafkaConsumer08<String> myConsumer = new FlinkKafkaConsumer08<String>("test", new SimpleStringSchema(),
properties);
//添加数据源,此处选用数据流的方式,将KafKa中的数据转换成Flink的DataStream类型
DataStream<String> stream = env.addSource(myConsumer);
//流计算,也是Flink的算子部分keyBy是通过key的形式进行分组,此处传入的0,表示是通过二元组的第一个元素也就是单词进行分组
//LineSplitter是算子的具体逻辑
DataStream<Tuple2<String, Integer>> counts = stream.flatMap(new LineSplitter())
.keyBy(0)
.sum(1);
//打印输出
counts.print();
//执行Job,Flink执行环境必须要有job的执行步骤,而以上的整个过程就是一个Job
env.execute("WordCount From KafKa data");
}
}
- 按照第一节的方法在本地启动Zookeeper和KafKa服务
- 启动对应topic的生产者并生产消息
- 最终可以在IDEA中看到消费的消息,并且消息经过Flink算子进行分词统计