Kafka学习笔记(二) :初探Kafka

看完上一篇,相信大家对消息系统以及Kafka的整体构成都有了初步了解,学习一个东西最好的办法,就是去使用它,今天就让我们一起窥探一下Kafka,并完成自己的处女作。

消息在Kafka中的历程

虽然我们掌握东西要一步一步来,但是我们在大致了解了一个东西后,会有利于我们对它的理解和学习,所以我们可以先来看一下一条消息从发出到最后被消息者接收到底经历了什么?

图片描述

上图简要的说明了消息在Kafka中的整个流转过程(假设已经部署好了整个Kafka系统,并创建了相应的Topic,分区等细节后续再单独讲):

  • 1.消息生产者将消息发布到具体的Topic,根据一定算法或者随机被分发到具体的分区中;
  • 2.根据实际需求,是否需要实现处理消息逻辑;
  • 3.若需要,则实现具体逻辑后将结果发布到输出Topic;
  • 4.消费者根据需求订阅相关Topic,并消费消息;

总的来说,怎么流程还是比较清晰和简单的,下面就跟我一起来练习Kafka的基本操作,最后实现一个单词计数的小demo。

基础操作

以下代码及相应测试在以下环境测试通过:Mac OS + JDK1.8,Linux系统应该也能跑通,Windows有兴趣的同学可以去官网下载相应版本进行相应的测试练习。

下载Kafka

Mac系统同学可以使用brew安装:

brew install kafka

Linux系统同学可以从官网下载源码解压,也可以直接执行以下命令:

cd 
mkdir test-kafka && cd test-kafka
curl -o kafka_2.11-1.0.1.tgz http://mirrors.tuna.tsinghua.edu.cn/apache/kafka/1.0.1/kafka_2.11-1.0.1.tgz
tar -xzf kafka_2.11-1.0.1.tgz
cd kafka_2.11-1.0.1

启动

Kafka使用Zookeeper来维护集群信息,所以这里我们先要启动Zookeeper,Kafka与Zookeeper的相关联系跟结合后续再深入了解,毕竟不能一口吃成一个胖子。

bin/zookeeper-server-start.sh config/zookeeper.properties

接着我们启动一个Kafka Server节点:

bin/kafka-server-start.sh config/server.properties

这时候Kafka系统已经算是启动起来了。

创建Topic

在一切就绪之后,我们要开始做极其重要的一步,那就是创建Topic,Topic是整个系统流转的核心,另外Topic本身也包含着很多复杂的参数,比如复制因子个数,分区个数等,这里为了从简,我们将对应的参数都设为1,方便大家测试:

bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic kakfa-test

其中参数的具体含义:

属性 功能
--create 代表创建Topic
--zookeeper zookeeper集群信息
--replication-factor 复制因子
--partitions 分区信息
--topic Topic名称

这时候我们已经创建好了一个叫kakfa-test的Topic了。

向Topic发送消息

在有了Topic后我们就可以向其发送消息:

bin/kafka-console-producer.sh --broker-list localhost:9092 --topic kakfa-test

然后我们向控制台输入一些消息:

this is my first test kafka
so good

这时候消息已经被发布在kakfa-test这个主题上了。

从Topic获取消息

现在Topic上已经有消息了,现在可以从中获取消息被消费:

bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic kafka-test --from-beginning

这时候我们可以在控制台看到:

this is my first test kafka
so good

至此我们就测试了最简单的Kafka Demo,希望大家能自己动手去试试,虽然很简单,但是这能让你对整个Kafka流程能更熟悉。

WordCount

下面我们来利用上面的一些基本操作来实现一个简单WordCount程序,它具备以下功能:

  • 1.支持词组持续输入,即生产者不断生成消息;
  • 2.程序自动从输入Topic中获取原始数据,然后经过处理,将处理结果发布在计数Topic中;
  • 3.消费者可以从计数Topic获取相应的WordCount的结果;

1.启动kafka

与上文的启动一样,按照其操作即可。

2.创建输入Topic

bin/kafka-topics.sh --zookeeper localhost:2181 --create --topic kafka-word-count-input --partitions 1 --replication-factor 1

3.向Topic输入消息

bin/kafka-console-producer.sh --broker-list localhost:9092 --topic kafka-word-count-input

4.流处理逻辑

这部分内容是整个例子的核心,这部分代码有Java 8+和Scala版本,个人认为流处理用函数式语法表达的更加简洁清晰,推荐大家用函数式的思维去尝试写以下,发现自己再也不想写Java匿名内部类这种语法了。

我们先来看一个Java 8的版本:

public class WordCount {
    public static void main(String[] args) throws Exception {
        Properties props = new Properties();
        props.put(StreamsConfig.APPLICATION_ID_CONFIG, "kafka-word-count");
        props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        props.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());
        props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());

        final StreamsBuilder builder = new StreamsBuilder();
        KStream<String, String> source = builder.<String, String>stream("kafka-word-count-input");
        Pattern pattern = Pattern.compile("\\W+");
        source
           .flatMapValues(value -> Arrays.asList(pattern.split(value.toLowerCase(Locale.getDefault()))))
           .groupBy((key, value) -> value)
           .count(Materialized.<String, Long, KeyValueStore<Bytes, byte[]>>as("counts-store")).mapValues(value->Long.toString(value))
           .toStream()
           .to("kafka-word-count-output");
        final KafkaStreams streams = new KafkaStreams(builder.build(), props);
        streams.start();
    }
}

是不是很惊讶,用java也能写出如此简洁的代码,所以说如果有适用场景,推荐大家尝试的用函数式的思维去写写java代码。

我们再来看看Scala版本的:


object WordCount {
  def main(args: Array[String]) {
    val props: Properties = {
      val p = new Properties()
      p.put(StreamsConfig.APPLICATION_ID_CONFIG, "kafka-word-count")
      p.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092")
      p.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String.getClass)
      p.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String.getClass)
      p
    }

    val builder: StreamsBuilder = new StreamsBuilder()
    val source: KStream[String, String] = builder.stream("kafka-word-count-input")
    source
      .flatMapValues(textLine => textLine.toLowerCase.split("\\W+").toIterable.asJava)
      .groupBy((_, word) => word)
      .count(Materialized.as[String, Long, KeyValueStore[Bytes, Array[Byte]]]("counts-store")).toStream.to("kafka-word-count-output")
    val streams: KafkaStreams = new KafkaStreams(builder.build(), props)
    streams.start()
  }
}

可以发现使用Java 8函数式风格编写的代码已经跟Scala很相似了。

5.启动处理逻辑

很多同学电脑上并没有装sbt,所以这里演示的利用Maven构建的Java版本,具体执行步骤请参考戳这里kafka-word-count上的说明。

6.启动消费者进程

最后我们启动消费者进程,并在生产者中输入一些单词,比如:

kafka-word-count-input

最后我们可以在消费者进程中看到以下输出:

bin/kafka-console-consumer.sh --topic kafka-word-count-output --from-beginning --bootstrap-server localhost:9092  --property print.key=true

kafka-word-count-output

总结

本篇文章主要是讲解了Kafka的基本运行过程和一些基础操作,但这是我们学习一个东西必不可少的一步,只有把基础扎实好,才能更深入的去了解它,理解它为什么这么设计,我在这个过程中也遇到很多麻烦,所以还是希望大家能够自己动手去实践一下,最终能收获更多。

308 声望
152 粉丝
0 条评论
推荐阅读
Scala-with-cats中文翻译(一):Type class与Implicit
最近在学习Cats,发现Scala-with-cats这本书写的不错,所以有想法将其翻译成中文,另外也可以在翻译的过程中加深理解,另外我会对每部分内容建议需要了解的程度,帮助大家更好的学习整体内容(有部分内容理解起来...

三分青年1阅读 2k

kafka数据分区不足删除操作
有时候由于特定的业务需要,我们的kafka分区的磁盘可能不够,这个时候我们需要自身删除磁盘数据或者使用脚本定时检测删除消费完的磁盘数据。但是有一个重要的点是:我们需要使用同一个topic主题,所以在删除数据之后...

startshineye阅读 1k

RabbitMQ、RocketMQ、Kafka延迟队列实现
延迟队列在实际项目中有非常多的应用场景,最常见的比如订单未支付,超时取消订单,在创建订单的时候发送一条延迟消息,达到延迟时间之后消费者收到消息,如果订单没有支付的话,那么就取消订单。

艾小仙阅读 896

国产 ETL工具 ETL产品 数据交换系统 ETL工具选型 需要考虑哪些因素
多数软件又为什么逐渐国产化? 长期以来,国内数据技术都由海外厂商主导。然而随着国际竞争环境日益激烈,争端所引发的技术卡脖子事件频发,面对特殊的大环境,全球化带来的科技创新共同体背后,国家IT产业实现自...

weigeonlyyou阅读 879

封面图
Kafka 分区 & 消费模式
下图以订单、运输、通知等信息,描述与kafka交互的过程,业务中的事件(如下单,支付,配送,评价,售后)会产生各类信息,最终以topic归类汇集到kafka中

老污的猫阅读 820

【Kafka】编译 Kafka2.7 源码并搭建源码环境(Ver 2.7.2)
Kafka 是通过 Scala 和 Java共同编写的语言,之所以选择2.7.2的版本是因为这个版本的Kafka是最后一版本保留ZK的版本。

Xander2阅读 291

问题盘点|使用 Prometheus 监控 Kafka,我们该关注哪些指标
Kafka 作为当前广泛使用的中间件产品,承担了重要/核心业务数据流转,其稳定运行关乎整个业务系统可用性。本文旨在分享阿里云 Prometheus 在阿里云 Kafka 和自建 Kafka 的监控实践。

阿里巴巴中间件阅读 607

308 声望
152 粉丝
宣传栏