apache kafka
当大数据运动开始时,它主要集中在批处理上。 分布式数据存储和查询工具(例如MapReduce,Hive和Pig)均设计用于批量处理数据,而不是连续处理数据。 企业每晚都会运行多个作业以从数据库中提取数据,然后进行分析,转换并最终存储数据。 最近,企业已经发现分析和处理数据和事件,因为它们发生 ,不只是一次每隔几个小时的电力。 但是,大多数传统的消息传递系统无法扩展以实时处理大数据。 因此,LinkedIn的工程师构建并开源了Apache Kafka :一种分布式消息传递框架,该框架通过扩展商品硬件来满足大数据需求。
在过去的几年中,Apache Kafka出现了,可以解决各种用例。 在最简单的情况下,它可能是用于存储应用程序日志的简单缓冲区。 与Spark Streaming之类的技术相结合,它可以用于跟踪数据更改并在将数据保存到最终目标之前对该数据采取操作 。 Kafka的预测模式使其成为检测欺诈的强大工具,例如在发生信用卡交易时检查其有效性,而无需等待数小时后的批处理。
本教程分为两部分,从如何在开发环境中安装和运行Kafka入手。 您将概述Kafka的体系结构,然后介绍开发现成的Apache Kafka消息传递系统。 最后,您将构建一个定制的生产者/消费者应用程序,该应用程序通过Kafka服务器发送和使用消息。 在本教程的后半部分,您将学习如何对消息进行分区和分组,以及如何控制Kafka使用者将使用的消息。
什么是Apache Kafka?
Apache Kafka是为扩展大数据而构建的消息传递系统。 与Apache ActiveMQ或RabbitMq相似 ,Kafka使构建在不同平台上的应用程序可以通过异步消息传递进行通信。 但是Kafka在以下关键方面与这些更传统的消息传递系统不同:
- 它旨在通过添加更多商用服务器来横向扩展。
- 它为生产者和消费者过程提供了更高的吞吐量。
- 它可以用于支持批处理和实时用例。
- 它不支持Java的面向消息的中间件API JMS 。
Apache Kafka的架构
在探讨Kafka的体系结构之前,您应该了解其基本术语:
- 生产者是可以将消息发布到主题的过程。
- 使用者是可以订阅一个或多个主题并使用发布到主题的消息的过程。
- 主题类别是将消息发布到的提要的名称。
- 代理是在单台计算机上运行的进程。
- 集群是一组一起工作的经纪人。
![图1:Kafka的体系结构](https://i-blog.csdnimg.cn/blog_migrate/c04d3b4f92fbccb2a31edeff49e66135.png)
图1. Kafka消息系统的体系结构
Apache Kafka的体系结构非常简单,在某些系统中可以带来更好的性能和吞吐量。 Kafka中的每个主题都像一个简单的日志文件。 生产者发布消息时,Kafka服务器会将其添加到给定主题的日志文件末尾。 服务器还分配一个偏移量 ,该偏移量是用于永久标识每个消息的数字。 随着消息数量的增加,每个偏移量的值都会增加; 例如,如果生产者发布三个消息,则第一个消息的偏移量可能为1,第二个消息的偏移量为2,第三个消息的偏移量为3。
当Kafka使用者首次启动时,它将向服务器发送拉取请求,要求检索偏移值大于0的特定主题的任何消息。服务器将检查该主题的日志文件并返回三则新消息。 。 使用者将处理消息,然后发送对偏移量大于3的消息的请求,依此类推。
在Kafka中,客户端负责记住偏移量计数和检索消息.Kafka服务器不跟踪或管理消息使用情况。 默认情况下,Kafka服务器会将邮件保留七天。 服务器中的后台线程检查并删除7天或更早的消息。 使用者可以访问消息,只要它们在服务器上即可。 它可以多次读取一条消息,甚至可以按相反的接收顺序读取消息。 但是,如果消费者在7天之内仍未检索到该消息,则它将丢失该消息。
卡夫卡基准
LinkedIn和其他企业的生产使用表明,通过正确配置,Apache Kafka每天能够处理数百GB的数据。 2011年,三位LinkedIn工程师使用基准测试来证明Kafka可以实现比ActiveMQ和RabbitMQ高得多的吞吐量。
Apache Kafka快速设置和演示
我们将在本教程中构建一个自定义应用程序,但让我们先从开箱即用的生产者和使用者安装和测试Kafka实例。
- 访问Kafka下载页面以安装最新版本(撰写本文时为0.9)。
- 将二进制文件解压缩到
software/kafka
文件夹中。 当前版本为software/kafka_2.11-0.9.0.0
。 - 更改您的当前目录以指向新文件夹。
- 通过执行以下命令来启动Zookeeper服务器:
bin/zookeeper-server-start.sh config/zookeeper.properties
。 - 通过执行以下命令来启动Kafka服务器:
bin/kafka-server-start.sh config/server.properties
。 - 创建一个可用于测试的测试主题:
bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic javaworld
。 - 启动一个简单的控制台使用者,该使用者可以使用发布到给定主题的消息,例如
javaworld
:bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic javaworld --from-beginning
。 - 启动一个简单的生产者控制台,该控制台可以将消息发布到测试主题:
bin/kafka-console-producer.sh --broker-list localhost:9092 --topic javaworld
。 - 尝试在生产者控制台中键入一则或两则消息。 您的消息应显示在使用者控制台中。
Apache Kafka的示例应用程序
您已经了解了Apache Kafka如何开箱即用。 接下来,让我们开发一个定制的生产者/消费者应用程序。 生产者将从控制台检索用户输入,并将每行作为消息发送给Kafka服务器。 使用者将检索给定主题的消息并将其打印到控制台。 在这种情况下,生产者和使用者组件是您自己的kafka-console-producer.sh
和kafka-console-consumer.sh
的实现。
首先创建一个Producer.java
类。 客户端类包含从控制台读取用户输入并将该输入作为消息发送到Kafka服务器的逻辑。
我们通过从java.util.Properties
类创建一个对象并设置其属性来配置生产者。 ProducerConfig类定义了所有可用的不同属性,但是Kafka的默认值足以满足大多数使用。 对于默认配置,我们只需要设置三个必需属性:
- BOOTSTRAP_SERVERS_CONFIG
- KEY_SERIALIZER_CLASS_CONFIG
- VALUE_SERIALIZER_CLASS_CONFIG
BOOTSTRAP_SERVERS_CONFIG (bootstrap.servers)
设置host:port对列表,用于建立与host1:port1,host2:port2,...
格式的Kakfa群集的初始连接。 即使我们的Kafka集群中有多个代理,我们也只需指定第一个代理的host:port
。 Kafka客户端将使用此值在代理上进行发现调用,该代理将返回集群中所有代理的列表。 在BOOTSTRAP_SERVERS_CONFIG
指定多个代理是一个好主意,这样,如果第一个代理关闭,客户端将可以尝试其他代理。
Kafka服务器希望消息以byte[] key, byte[] value
格式显示。 Kafka的客户端库允许我们使用更友好的类型(如String
和int
来发送消息,而不是转换每个键和值。 该库会将它们转换为适当的类型。 例如,示例应用程序没有特定于消息的密钥,因此我们将null用作密钥。 对于该值,我们将使用String
,这是用户在控制台上输入的数据。
要配置消息密钥 ,我们在org.apache.kafka.common.serialization.ByteArraySerializer
上设置KEY_SERIALIZER_CLASS_CONFIG
的值。 之所以可行,是因为不需要将null转换为byte[]
。 对于消息值 ,我们在org.apache.kafka.common.serialization.StringSerializer
上设置VALUE_SERIALIZER_CLASS_CONFIG
,因为该类知道如何将String
转换为byte[]
。
自定义键/值对象
与StringSerializer
相似,Kafka为其他原语(例如int
和long
提供了序列化器。 为了对键或值使用自定义对象,我们需要创建一个实现org.apache.kafka.common.serialization.Serializer
的类。 然后,我们可以添加逻辑以将类序列化为byte[]
。 我们还必须在使用者代码中使用相应的反序列化器。
卡夫卡制片人
在用必要的配置属性填充Properties
类之后,我们可以使用它来创建KafkaProducer
的对象。 之后,无论何时要将消息发送到Kafka服务器,我们都会创建一个ProducerRecord
对象,并使用该记录调用KafkaProducer
的send()
方法来发送消息。 ProducerRecord
具有两个参数:消息应发布到的主题名称和实际消息。 使用生产者完成操作后,请不要忘记调用Producer.close()
方法:
清单1. KafkaProducer
public class Producer {
private static Scanner in;
public static void main(String[] argv)throws Exception {
if (argv.length != 1) {
System.err.println("Please specify 1 parameters ");
System.exit(-1);
}
String topicName = argv[0];
in = new Scanner(System.in);
System.out.println("Enter message(type exit to quit)");
//Configure the Producer
Properties configProperties = new Properties();
configProperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"localhost:9092");
configProperties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.ByteArraySerializer");
configProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
org.apache.kafka.clients.producer.Producer producer = new KafkaProducer<String, String>(configProperties);
String line = in.nextLine();
while(!line.equals("exit")) {
ProducerRecord<String, String> rec = new ProducerRecord<String, String>(topicName, line);
producer.send(rec);
line = in.nextLine();
}
in.close();
producer.close();
}
}
配置消息使用者
接下来,我们将创建一个订阅主题的简单使用者。 每当将新消息发布到该主题时,它将阅读该消息并将其打印到控制台。 消费者代码与生产者代码非常相似。 我们首先创建一个java.util.Properties
对象,设置其消费者特定的属性,然后使用它创建一个新的KafkaConsumer
对象。 ConsumerConfig类定义了我们可以设置的所有属性。 只有四个强制属性:
- BOOTSTRAP_SERVERS_CONFIG(bootstrap.servers)
- KEY_DESERIALIZER_CLASS_CONFIG(key.deserializer)
- VALUE_DESERIALIZER_CLASS_CONFIG(value.deserializer)
- GROUP_ID_CONFIG(bootstrap.servers)
就像我们对生产者类所做的一样,我们将使用BOOTSTRAP_SERVERS_CONFIG
为消费者类配置主机/端口对。 通过此配置,我们可以以host1:port1,host2:port2,...
格式建立与Kakfa群集的初始连接。
如前所述,Kafka服务器希望消息以byte[]
键和byte[]
值格式显示,并且具有自己的实现,可以将不同类型的序列化为byte[]
。 就像我们与生产者一样,在消费者方面,我们必须使用自定义反序列化器将byte[]
转换回适当的类型。
在示例应用程序的情况下,我们知道生产者将ByteArraySerializer
用于密钥,将StringSerializer
用于值。 在客户端,因此,我们需要使用org.apache.kafka.common.serialization.ByteArrayDeserializer
密钥和org.apache.kafka.common.serialization.StringDeserializer
的价值。 将这些类设置为KEY_DESERIALIZER_CLASS_CONFIG
和VALUE_DESERIALIZER_CLASS_CONFIG
值将使使用者能够反序列化生产者发送的byte[]
编码类型。
最后,我们需要设置GROUP_ID_CONFIG
的值。 这应该是字符串格式的组名。 我将在稍后解释有关此配置的更多信息。 现在,只看一下具有四个必填属性集的Kafka使用者:
翻译自: https://www.infoworld.com/article/3060078/big-data-messaging-with-kafka-part-1.html
apache kafka