流数据越来越受到许多组织的关注,并且大多数应用程序需要使用生产者-消费者模型来实时摄取和处理数据。 市场上目前存在许多消息传递解决方案,但为应对与物联网,大型基于Web的应用程序和相关大数据项目相关的现代部署的挑战而构建的解决方案很少。
Apache Kafka由LinkedIn构建,以解决这些挑战,并已部署在许多项目中。 Apache Kafka是一个快速,可扩展,持久和分布式的消息传递系统。
本文的目的是使用端到端示例和示例代码向您展示如何:
- 安装,配置和启动Kafka
- 创建新主题
- 编写并运行Java生产者以将消息发布到主题
- 编写并运行Java使用者以读取和处理主题中的消息
学分
此内容部分基于Apache Kafka项目提供的文档。
我们添加了简短逼真的示例程序,这些示例程序说明了如何使用Kafka编写实际程序。
先决条件
您将需要基本的Java编程技能以及访问以下内容的权限:
- 阿帕奇卡夫卡0.9.0
- Apache Maven 3.0或更高版本
- 吉特
安装
步骤1:下载Kafka
下载Apache Kafka 0.9.0发行版并解压缩。
$ tar -xzf kafka_2.11-0.9.0.0.tgz
$ cd kafka_2.11-0.9.0.0
步骤2:启动服务器
启动ZooKeeper服务器; Kafka具有内置的单节点Zookeeper配置。
$ bin/zookeeper-server-start.sh config/zookeeper.properties &
[2016-02-08 14:59:28,275] INFO Reading configuration from: config zookeeper.properties (org.apache.zookeeper.server.quorum.QuorumPeerConfig)
[2016-02-08 14:59:28,276] INFO autopurge.snapRetainCount set to 3 (org.apache.zookeeper.server.DatadirCleanupManager)
...
请注意,这将在后台启动Zookeeper。 要停止Zookeeper,您需要将其放回前台并使用control-C,或者需要找到该进程并将其杀死。 您现在可以启动Kafka服务器本身:
$ bin/kafka-server-start.sh config/server.properties
[2016-02-08 15:10:29,945] INFO KafkaConfig values: ..
....
与Zookeeper一样,它在后台运行Kafka代理。 要停止Kafka,您需要将其放回前台或找到该进程,然后使用kill明确杀死它。
步骤3:为示例程序创建主题
消息按主题组织,生产者在其上发布消息,而消费者从中读取消息。 我们的示例应用程序使用了两个主题:快速消息和摘要标记。 以下命令创建主题:
$ bin/kafka-topics.sh --create --zookeeper localhost:2181 \
--replication-factor 1 --partitions 1 --topic fast-messages
$ bin/kafka-topics.sh --create --zookeeper localhost:2181 \
--replication-factor 1 --partitions 1 --topic summary-markers
这些可以列出:
$ bin/kafka-topics.sh --list --zookeeper localhost:2181
fast-messages
summary-markers
运行Kafka命令时,您将看到来自Kafka进程的日志消息。 如果这些分散您的注意力,您可以切换到其他窗口。
注意:可以将代理配置为自动创建客户端应用程序提到的新主题,但这通常被认为有些危险,因为对主题名称的拼写错误不会导致失败。
运行您的第一个Kafka应用程序
此时,您应该在计算机上运行一个可运行的Kafka代理。 下一步是编译示例程序,并尝试其工作方式。
1-编译并打包示例程序
使用以下命令克隆并编译存储库:
$ git clone https://github.com/mapr-demos/kafka-sample-programs.git
$ cd kafka-sample-programs/
$ mvn clean package
为方便起见,示例程序项目被设置为使Maven包目标生成一个可执行文件target / kafka-example,其中包括所有示例程序和依赖项。
2-启动示例消费者
使用以下命令启动使用者:
$ target/kafka-example consumer
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
现在,使用者开始使用,并收听有关快速消息和摘要标记主题的所有消息
由于目前没有任何讯息,因此目前不会发生任何事情
3-运行示例生产者
在新的终端窗口中,使用以下命令运行示例生产者:
$ target/kafka-example producer
Sent msg number 0
Sent msg number 1000
...
Sent msg number 998000
Sent msg number 999000
生产者将大量消息发送给快速消息,并将偶尔的消息发送给摘要标记。
在另一个窗口中运行的使用者接收并处理来自这些主题的所有消息。
$ target/kafka-example consumer
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Got 31003 records after 0 timeouts
1 messages received in period, latency(min, max, avg, 99%) = 20352, 20479, 20416.0, 20479 (ms)
1 messages received overall, latency(min, max, avg, 99%) = 20352, 20479, 20416.0, 20479 (ms)
1000 messages received in period, latency(min, max, avg, 99%) = 19840, 20095, 19968.3, 20095 (ms)
1001 messages received overall, latency(min, max, avg, 99%) = 19840, 20479, 19968.7, 20095 (ms)
...
1000 messages received in period, latency(min, max, avg, 99%) = 12032, 12159, 12119.4, 12159 (ms)
998001 messages received overall, latency(min, max, avg, 99%) = 12032, 20479, 15073.9, 19583 (ms)
1000 messages received in period, latency(min, max, avg, 99%) = 12032, 12095, 12064.0, 12095 (ms)
999001 messages received overall, latency(min, max, avg, 99%) = 12032, 20479, 15070.9, 19583 (ms)
如果再次运行生产者,则将在消费者终端窗口中看到新消息。
快速查看生产者和消费者代码
至此,您已经在运行Kafka,这是一个发送和使用消息的简单Kafka应用程序。 现在是时候查看代码并了解如何创建应用程序了。
依存关系
要创建Kafka生产者或使用者(即Kafka客户端应用程序),必须将以下依赖项添加到Maven项目中:
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>0.9.0.0</version>
</dependency>
制片人
样本Producer是具有main()方法的经典Java应用程序,该应用程序必须:
- 初始化和配置生产者
- 使用生产者发送消息
1-生产者初始化
创建生产者非常简单,您只需实现带有一组属性的org.apache.kafka.clients.producer.KafkaProducer
类,如下所示:
producer = new KafkaProducer(properties);
在此示例中,配置在属性文件中外部化,其中包含以下条目:
bootstrap.servers=localhost:9092
acks=all
...
block.on.buffer.full=true
对于此介绍,最重要的属性是:
-
bootstrap.servers
列出了您在本教程前面部分启动的Kafka服务器/群集的主机和端口。
其他属性用于控制消息的发送和序列化方式。 您可以在Kafka文档的Producer Configs一章中找到有关所有属性的信息。
2-消息发布
一旦有了生产者实例,就可以使用ProducerRecord类将消息发布到主题。 ProducerRecord类是键/值对,其中:
- 关键是话题
- 值就是信息
您可能会直接向该主题发送消息:
...
producer.send(new ProducerRecord("fast-messages", "This is a dummy message"));
...
请注意,还有其他ProducerRecord
构造函数允许您使用更多构造函数参数,例如消息键,分区号,但是在此简单教程中未使用这些参数。
示例应用程序生产者使用循环发送消息以发送:
- 每次迭代都向快速消息主题发送1条消息
- 每1000次迭代有1条标记消息发送给快速消息主题
- 每1000次迭代到摘要标记1条消息
3-生产者端
使用完生产者后,请使用producer.close()
方法阻止该过程,直到将所有消息发送到服务器为止。 在finally块中使用此调用以确保被调用。 Kafka生产者也可以尝试使用资源构造 。
...
} finally {
producer.close();
}
...
4-生产者执行
如前所述,生产者是一个简单的Java类,在此示例应用程序中,生产者从运行应用程序启动,如下所示:
...
Producer.main(args);
...
现在您知道了如何将消息发送到Kafka服务器,让我们看一下使用者。
消费者
消费者类(类似于生产者)是具有主要方法的简单Java类。
该样本使用者使用HdrHistogram库来记录和分析从快速消息主题接收的消息,并使用Jackson来解析JSON消息。
这就是为什么在pom.xml文件中看到以下依赖项的原因:
<dependency>
<groupId>org.hdrhistogram</groupId>
<artifactId>HdrHistogram</artifactId>
<version>2.1.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.1</version>
</dependency>
现在让我们关注消费者代码。
1-消费者初始化
首先要做的是创建org.apache.kafka.clients.consumer.KafkaConsumer
类的使用者实例,该实例具有一组属性,如下所示:
consumer = new KafkaConsumer(properties);
在此示例中,属性在file中被外部化,具有以下条目:
bootstrap.servers=localhost:9092
group.id=test
enable.auto.commit=true
...
max.partition.fetch.bytes=2097152
对于此介绍,最重要的属性是
- bootstrap.servers是您在本教程前面部分中启动的Kafka服务器/集群的主机和端口
- 该使用者所属的使用者进程组的group.id。
其他属性用于控制消息的使用方式。 您可以在Kafka文档的“ 使用者配置”一章中找到有关所有属性的信息。
2-主题订阅
使用者可以订阅一个或多个主题,在此示例中,使用者将使用以下代码收听来自两个主题的消息:
consumer.subscribe(Arrays.asList("fast-messages", "summary-markers"));
3-消息消耗
现在,您的使用者已经订阅了主题,该使用者现在可以循环轮询来自主题的消息。 循环看起来像 :
...
while (true) {
ConsumerRecords records = consumer.poll(200);
...
}
...
在循环中反复调用poll方法。 对于每个呼叫,消费者将从主题中读取记录。 对于每次读取,它跟踪偏移量,以便能够在下一个调用中从正确的消息中读取。 轮询方法超时(以毫秒为单位)。 如果没有可用数据,它将等待长达该时间。
poll方法的返回对象是一个Iterable,它包含接收到的记录,因此您只需要在每个记录上循环以处理它们。 在使用者中处理消息的代码如下所示:
...
for (ConsumerRecord record : records) {
switch (record.topic()) {
case "fast-messages":
// deal with messages from fast-messages topic
...
case "summary-markers":
// deal with messages from summary-markers topic
...
break;
default:
}
}
...
在示例应用程序中,消费者仅根据生产者发送消息的顺序来消费消息,从而使用以下逻辑处理来自快速消息主题的消息:
- 对于具有类型测试的每条JSON消息, 延迟都会添加到直方图统计信息中
- 处理带有类型标记的JSON消息时,将打印统计信息并重置 。
4-消费者端
一旦使用完消费者,请使用consumer.close()
方法释放资源。 这在多线程应用程序中尤其重要。 样本使用者不调用此方法,因为使用Ctrl + C停止该方法将停止整个JVM。
5-生产者执行
如前所述,消费者是一个简单的Java类,在此示例应用程序中,消费者从运行应用程序启动,如下所示:
...
Consumer.main(args);
...
结论
在本文中,您学习了如何使用以下方法创建简单的Kafka 0.9.x应用程序:
- 将JSON消息发布到多个主题的生产者
- 接收JSON消息并根据消息内容计算统计信息的使用者。
这个应用程序非常简单,您可以扩展它以测试Kafka的其他有趣功能:
- 使用不同的组添加新使用者,以不同方式处理数据,例如将数据保存到NoSQL数据库(如HBase或MapR-DB)中
- 为主题添加新的分区和使用者,以为您的应用程序提供高可用性。
最后,尽管此示例基于Apache Kafka,但相同的代码将使用MapR-Streams直接在MapR集群上工作, MapR-Streams是与Kafka 0.9.0 API兼容的集成消息传递系统。 使用MapR-Streams,您可以简化应用程序的生产部署,因为它已集成到MapR数据平台中,因此您将可以部署和管理单个集群。 使用MapR Streams进行消息传递还提供了与MapR融合数据平台相关的附加可伸缩性,安全性和大数据服务。
翻译自: https://www.javacodegeeks.com/2016/02/getting-started-sample-programs-apache-kafka-0-9.html