超详细的Kafka入门,看这篇就够了

超详细的Kafka入门,看这篇就够了

  • kafka的介绍
  • kafka的术语
  • kafka核心Api
  • kafka初の体验
    • 1.windows安装kafka
    • 2.Kafka Producer与Kafka Consumer配置说明
      • Kafka Producer
      • Kafka Consumer
    • 3.永远的Hello Word
      • 1.新建一个Spring Boot工程,命名为:“kafka”。
      • 2.pom.xml
      • 3.application.yml
      • 4.Producer
      • 5.Consumer
      • 6.主启动
      • 7.测试类
      • 8.测试
    • 4.总结

kafka的介绍

Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。
Kafka 有如下特性:

  • 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间复杂度的访问性能。
  • 高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒100K条以上消息的传输。
  • 支持Kafka Server间的消息分区,及分布式消费,同时保证每个Partition内的消息顺序传输。
  • 同时支持离线数据处理和实时数据处理。
  • Scale out:支持在线水平扩展。

kafka的术语

  • Broker:Kafka集群包含一个或多个服务器,这种服务器被称为broker。
  • Topic:每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic。(物理上不同Topic的消息分开存储,逻辑上一个Topic的消息虽然保存于一个或多个broker上但用户只需指定消息的Topic即可生产或消费数据而不必关心数据存于何处)
  • Partition:Partition是物理上的概念,每个Topic包含一个或多个Partition。
  • Producer:负责发布消息到Kafka broker。
  • Consumer:消息消费者,向Kafka broker读取消息的客户端。
  • Consumer Group:每个Consumer属于一个特定的Consumer Group(可为每个Consumer指定group name,若不指定group name则属于默认的group)。

kafka核心Api

kafka有四个核心API

  • 应用程序使用producer API发布消息到1个或多个topic中。
  • 应用程序使用consumer API来订阅一个或多个topic,并处理产生的消息。
  • 应用程序使用streams API充当一个流处理器,从1个或多个topic消费输入流,并产生一个输出流到1个或多个topic,有效地将输入流转换到输出流。
  • connector API允许构建或运行可重复使用的生产者或消费者,将topic链接到现有的应用程序或数据系统。

kafka初の体验

1.windows安装kafka

windows 上 Kafka 启动

2.Kafka Producer与Kafka Consumer配置说明

Kafka Producer

  • bootstrap.servers: kafka的地址。
  • acks:消息的确认机制,默认值是0。
    acks=0:如果设置为0,生产者不会等待kafka的响应。
    acks=1:这个配置意味着kafka会把这条消息写到本地日志文件中,但是不会等待集群中其他机器的成功响应。
    acks=all:这个配置意味着leader会等待所有的follower同步完成。这个确保消息不会丢失,除非kafka集群中所有机器挂掉。这是最强的可用性保证。
  • retries:配置为大于0的值的话,客户端会在消息发送失败时重新发送。
  • batch.size:当多条消息需要发送到同一个分区时,生产者会尝试合并网络请求。这会提高client和生产者的效率。
  • key.serializer: 键序列化,默认org.apache.kafka.common.serialization.StringDeserializer。
  • value.deserializer:值序列化,默认org.apache.kafka.common.serialization.StringDeserializer。

还有更多配置,可以去查看官方文档,这里就不在说明了。

Kafka Consumer

  • bootstrap.servers: kafka的地址。
  • group.id:组名 不同组名可以重复消费。例如你先使用了组名A消费了kafka的1000条数据,但是你还想再次进行消费这1000条数据,并且不想重新去产生,那么这里你只需要更改组名就可以重复消费了。
  • enable.auto.commit:是否自动提交,默认为true。
  • auto.commit.interval.ms: 从poll(拉)的回话处理时长。
  • session.timeout.ms:超时时间。
  • max.poll.records:一次最大拉取的条数。
  • auto.offset.reset:消费规则,默认earliest 。
    earliest: 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费 。
    latest: 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据 。
    none: topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常。
  • key.serializer: 键序列化,默认org.apache.kafka.common.serialization.StringDeserializer。
  • value.deserializer:值序列化,默认org.apache.kafka.common.serialization.StringDeserializer。

3.永远的Hello Word

下面,我们通过在Spring Boot应用中整合kafka,并实现一个简单的发送、接收消息的例子来对kafka有一个直观的感受和理解。

1.新建一个Spring Boot工程,命名为:“kafka”。

超详细的Kafka入门,看这篇就够了_第1张图片

2.pom.xml


<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.0modelVersion>
    <groupId>com.dyh.kafkagroupId>
    <artifactId>kafkaartifactId>
    <version>1.0-SNAPSHOTversion>
    
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.3.10.RELEASEversion>
        <relativePath/> 
    parent>

    <dependencies>
        
        <dependency>
            <groupId>org.springframework.kafkagroupId>
            <artifactId>spring-kafkaartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-autoconfigureartifactId>
        dependency>
    dependencies>
project>

3.application.yml

server:
  port: 1234

spring:
#  devtools:
#    restart:
#      enabled: true

  kafka:
    # 以逗号分隔的地址列表,用于建立与Kafka集群的初始连接(kafka 默认的端口号为9092)
    #bootstrap-servers: kmanager.ahsl.lab:9092
    #bootstrap-servers: b-2.wangzx-kafka-test0.w3xikl.c2.kafka.cn-north-1.amazonaws.com.cn:9092,b-1.wangzx-kafka-test0.w3xikl.c2.kafka.cn-north-1.amazonaws.com.cn:9092
    bootstrap-servers: localhost:9092
    producer:
#      properties:
#        #事务ID
#        enable.idempotence: true
      # 发生错误后,消息重发的次数。
      retries: 1
      #当有多个消息需要被发送到同一个分区时,生产者会把它们放在同一个批次里。该参数指定了一个批次可以使用的内存大小,按照字节数计算。
      batch-size: 16384
      # 设置生产者内存缓冲区的大小。
      buffer-memory: 33554432
      # 键的序列化方式
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      # 值的序列化方式
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
      # acks=0 : 生产者在成功写入消息之前不会等待任何来自服务器的响应。
      # acks=1 : 只要集群的首领节点收到消息,生产者就会收到一个来自服务器成功响应。
      # acks=all :只有当所有参与复制的节点全部收到消息时,生产者才会收到一个来自服务器的成功响应。
      acks: 1
    consumer:
      properties:
        #客户端超时时间
        session.timeout.ms: 600000
      # 自动提交的时间间隔 在spring boot 2.X 版本中这里采用的是值的类型为Duration 需要符合特定的格式,如1S,1M,2H,5D
      auto-commit-interval: 1S
      # 该属性指定了消费者在读取一个没有偏移量的分区或者偏移量无效的情况下该作何处理:
      # latest(默认值)在偏移量无效的情况下,消费者将从最新的记录开始读取数据(在消费者启动之后生成的记录)
      # earliest :在偏移量无效的情况下,消费者将从起始位置读取分区的记录
      auto-offset-reset: earliest
      # 是否自动提交偏移量,默认值是true,为了避免出现重复数据和数据丢失,可以把它设置为false,然后手动提交偏移量
      enable-auto-commit: false
      # 键的反序列化方式
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      # 值的反序列化方式
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      group-id: topic-dyh-group
    listener:
      missing-topics-fatal: false
      # 在侦听器容器中运行的线程数。
      concurrency: 10
      ack-mode: manual

logging:
  level:
    org:
      springframework:
        kafka: ERROR # spring-kafka INFO 日志太多了,所以我们限制只打印 ERROR 级别
      apache:
        kafka: ERROR # kafka INFO 日志太多了,所以我们限制只打印 ERROR 级别





4.Producer

package com.dyh.kafka.producer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.UUID;

/**
 * @ClassName: Producer
 * @author: 〆、dyh
 * @since: 2022/12/21 15:23
 */

@Component
public class Producer {
    @Autowired
    private KafkaTemplate kafkaTemplate;

    public void send(String msg) {
        kafkaTemplate.send("topic-dyh", msg);
    }
}

5.Consumer

package com.dyh.kafka.consumer;

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Objects;

/**
 * @ClassName: Consumer
 * @author: 〆、dyh
 * @since: 2022/12/21 15:25
 */
@Component
public class Consumer {

    @KafkaListener(id = "id",
            topics = "topic-dyh",
            groupId = "topic-dyh-group")
    public void onMessage(ConsumerRecord<Long, String> record, Acknowledgment acknowledgment) {
        if (Objects.nonNull(record.value())) {
            System.out.println("线程编号:" + Thread.currentThread().getId() + ",消息内容:" + record.value());
            try {
                System.out.println("消费:" + record.value());
                //手动提交
                acknowledgment.acknowledge();
            } catch (Exception e) {
                e.printStackTrace();
                acknowledgment.acknowledge();
            } finally {
                acknowledgment.acknowledge();
            }
        }

    }
}

6.主启动

package com.dyh.kafka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @ClassName: Application
 * @author: 〆、dyh
 * @since: 2022/12/21 15:26
 */
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

7.测试类

package com.dyh.kafka;

import com.dyh.kafka.producer.Producer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @ClassName: Test
 * @author: 〆、dyh
 * @since: 2022/12/21 15:35
 */
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestKafka {

    @Autowired
    private Producer producer;

    @Test
    public void TestSend() {
        System.out.println("生产一头牛");
        producer.send("一头牛");
    }
}

8.测试

控制台输出

生产一头牛
线程编号:21,消息内容:一头牛
消费:一头牛

4.总结

简单的开发一个kafka的程序需要以下步骤:

  • 成功搭建kafka服务器,并成功启动!
  • 得到kafka服务信息,然后在代码中进行相应的配置。
  • 配置完成之后,监听kafka中的消息队列是否有消息产生。
  • 将产生的数据进行业务逻辑处理!

当然项目我放在gitee上了,有兴趣的可以看看。https://gitee.com/DuanYuHong/kafka

你可能感兴趣的:(Kafka,kafka,java,分布式)