Kafka——Streams流处理示例

Kafka Streams

1、概述

Kafka一直被认为是一个强大的消息中间件,它实现了高吞吐、高可用和低延时的消息传输能力,这让它成为流式处理系统中完美的数据来源。目前通用的一些流式处理框架如Apache Spark、Apache Flink、Apache Storm等都可以将Kafka作为可靠的数据来源。但遗憾的是,在0.l0.x版本之前,Kafka还并不具备任何数据处理的能力,但在此之后,Kafka Streams应运而生。

Kafka Streams是一个用于处理和分析数据的客户端库。它先把存储在Kafka中的数据进行处理和分析,然后将最终所得的数据结果回写到Kafka或发送到外部系统。它建立在一些非常重要的流式处理概念之上,例如适当区分事件时间和处理时间、窗口支持,以及应用程序状态的简单(高效)管理。同时,它也基于Kafka中的许多概念,例如通过划分主题进行扩展。此外,由于这个原因,它作为一个轻量级的库可以集成到应用程序中。这个应用程序可以根据需要独立运行、在应用程序服务器中运行、作为Docker容器,或者通过资源管理器(如Mesos)进行操作。

Kafka Streams直接解决了流式处理中的很多问题:

  • 毫秒级延迟的逐个事件处理。
  • 有状态的处理,包括连接(join)和聚合类操作。
  • 提供了必要的流处理原语,包括高级流处理DSL和低级处理器API。高级流处理DSL提供了常用流处理变换操作,低级处理器API支持客户端自定义处理器并与状态仓库交互。
  • 使用类似DataFlow的模型对无序数据进行窗口化处理。
  • 具有快速故障切换的分布式处理和容错能力。
  • 无停机滚动部署。

2、单词统计

单词统计是流式处理领域中最常见的示例,这里我们同样使用它来演示一下Kafka Streams的用法。在Kafka的代码中就包含了一个单词统计的示例程序,即org.apache.kafka.streams. examples.wordcount.WordCountDemo,这个示例中以硬编码的形式用到了两个主题:
streams-plaintext-inputstreams-wordcount-output。为了能够使示例程序正常运行,我们需要预先准备好这两个主题:

./kafka-topics.sh --create --bootstrap-server localhost:9092 --topic streams-plaintext-input --replication-factor 1 --partitions 1

./kafka-topics.sh --create --bootstrap-server localhost:9092 --topic streams-wordcount-output --replication-factor 1 --partitions 1

这两个主题的详细信息如下:

./kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic streams-plaintext-input,streams-wordcount-output

在这里插入图片描述

之后就可以运行WordCountDemo这个示例:

./kafka-run-class.sh org.apache.kafka.streams.examples.wordcount.WordCountDemo

这个示例程序将从主题streams-plaintext-input中读取消息,然后对读取的消息执行单词统计,并将结果持续写入主题streams-wordcount-output。

使用Kafka自带的console producer来生产一些输入数据供WordCount程序消费:

./kafka-console-producer.sh --bootstrap-server localhost:9092 --topic streams-plaintext-input

再运行console consumer脚本来验证WordCount程序的计算结果:

./kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic streams-wordcount-output --property print.key=true --property value.deserializer=org.apache.kafka.common.serialization.LongDeserializer 

输入一些单词:
在这里插入图片描述
统计结果:输出结果中的第一列是消息的key,这里表示被计数的单词,第二列是消息的value,这里表示该单词的最新计数。
在这里插入图片描述

下面我们通过WordCountDemo程序来了解一下Kafka Streams的开发方式,WordCountDemo程序如下所示:

<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-streams</artifactId>
    <version>2.3.0</version>
</dependency>
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KafkaStreams;
import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.StreamsConfig;
import org.apache.kafka.streams.kstream.KStream;
import org.apache.kafka.streams.kstream.KTable;
import org.apache.kafka.streams.kstream.Produced;

import java.util.Arrays;
import java.util.Locale;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;

/**
 * @Author: acton_zhang
 * @Date: 2023/8/17 11:41 下午
 * @Version 1.0
 * 单词统计
 */
public class WordCountDemo {
    public static void main(String[] args) {
        //构建Kafka Streams的配置
        Properties props = new Properties();
        //每个Kafka Streams应用程序必须要有一个application.id,这个applicationID用于协调应用实例
        //也用于命名内部的本地存储和相关主题。在整个Kafka集群中,applicationId必须是唯一的
        props.put(StreamsConfig.APPLICATION_ID_CONFIG, "streams-wordcount");
        //bootstrap.servers配置的是Kafka集群的地址,必填
        props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        //最大缓冲字节数
        props.put(StreamsConfig.CACHE_MAX_BYTES_BUFFERING_CONFIG, 0);
        //default.key.serde设置key的序列化器
        props.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName());
        //default.value.serde设置value的序列化器
        props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName());

        //创建StreamBuilder实例
        StreamsBuilder builder = new StreamsBuilder();
        //创建一个KStream实例,并设定了输入主题streams-plaintext-input
        KStream<String, String> source = builder.stream("streams-plaintext-input");
        //具体的单词统计逻辑
        //KStream是一个由键值对构成的抽象记录流,每个键值对是一个独立单元,即使相同的key也不会被覆盖,类似数据库的插入操作
        //KTable可以理解成一个基于表主键的日志更新流,相同key的每条记录只保存最新的一条记录,类似数据库中基于主键的更新
        //无论记录流(用KStream定义),还是更新日志流(用KTable定义),都可以从一个或多个Kafka主题数据源来创建。
        //一个KStream可以与另一个KStream或KTable进行Join操作,或者聚合成一个KTable。同样,一个KTable也可以转换成一个KStream。
        //KStream和KTable都提供了一系列转换操作,每个转换操作都可以转化为一个KStream或KTable对象,将这些转换操作连接在一起就构成了一个处理器拓扑。
        KTable<String, Long> counts = source.flatMapValues(value -> Arrays.asList(
                value.toLowerCase(Locale.getDefault()).split(" ")))
                .groupBy((key, value) -> value)
                .count();
        //toStream().to()将单词统计结果写入输出主题streams-wordcount-output,key是String类型,value是Long类型
        counts.toStream().to("streams-wordcount-output",
                Produced.with(Serdes.String(), Serdes.Long()));
        //基于拓扑和配置来订阅一个KafkaStreams对象
        final KafkaStreams streams = new KafkaStreams(builder.build(), props);
        final CountDownLatch latch = new CountDownLatch(1);
        Runtime.getRuntime().addShutdownHook(new Thread("streams-wordcount-shutdown-hook") {
            @Override
            public void run() {
                streams.close();
                latch.countDown();
            }
        });
        //启动KafkaStreams引擎
        try {
            streams.start();
            latch.await();
        } catch (Throwable e) {
            System.exit(1);
        }
        System.exit(0);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java Kafka处理的最佳实践有以下几个方面: 1. 使用Spring Kafka库进行处理:Spring Kafka提供了与Kafka集成的注解处理器和消费者,使得编写和管理Kafka消费者变得更加简单和方便。通过使用@KafkaListener注解,可以轻松创建和配置Kafka消费者,同时可以通过参数指定消费者组和其他配置选项来实现更高级的功能。 2. 使用Kafka Streams API进行复杂处理:对于更复杂的处理需求,可以使用Kafka提供的完全集成的Streams API。Streams API允许构建执行非平凡处理应用程序,如的聚合和的连接。使用Streams API可以更灵活地处理和转换数据,实现更复杂的业务逻辑。 3. 优化Kafka消费者的性能:为了提高Kafka处理的性能,可以采取一些优化措施。例如,可以使用多线程来并行处理多个数据,使用批量消费来减少网络开销,设置适当的消费者配置参数来优化消费者的性能等[2]。 4. 处理消息顺序和重复问题:在处理中,消息的顺序和重复问题是需要考虑的重要因素。可以通过使用分区器和键来确保消息按顺序处理,并使用幂等性和事务来处理重复消息,从而解决这些问题。 总结起来,Java Kafka处理的最佳实践包括使用Spring Kafka库进行简单的处理,使用Kafka Streams API进行复杂的处理,优化Kafka消费者的性能,以及处理消息顺序和重复问题。通过遵循这些最佳实践,可以更好地实现和管理Java Kafka处理应用程序。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [【项目实战】Java 开发 Kafka 消费者](https://blog.csdn.net/qq_37967783/article/details/131715447)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [超详细 kafka 入门(最佳实践)](https://blog.csdn.net/weixin_38405253/article/details/117393362)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值