Introducción a Kafka

prefacio

Como artículo introductorio, es principalmente para comprender el concepto de Kafka, así como algunas operaciones y usos básicos.

introducir

El funcionario hizo una introducción relativamente completa para Kafka: Kafka Chinese Documentation - ApacheCN

Kafka es una plataforma de salida distribuida.

Como plataforma de procesamiento de flujo, tiene tres características:

  1. Le permite publicar y suscribirse a registros de transmisión. Este aspecto es similar a las colas de mensajes o los sistemas de mensajería empresarial.
  2. Los registros de transmisión se pueden almacenar y tener una mejor tolerancia a fallas.
  3. Los registros de transmisión se pueden procesar a medida que se generan.

Se puede utilizar en dos amplias categorías de aplicaciones:

  1. Construya canalizaciones de transmisión de datos en tiempo real que obtengan datos de manera confiable entre sistemas o aplicaciones. (equivalente a la cola de mensajes)
  2. Cree aplicaciones de transmisión en tiempo real que transformen o influyan en estos datos de transmisión. (es decir, procesamiento de flujo, a través de cambios internos entre tema y tema de flujo kafka)

Concepto y Descripción

Como clúster, kafka puede ejecutarse en uno o más servidores

Kafka topicclasifica los datos almacenados por

Cada registro contiene un key, un valuey untimestamp

Una estructura de kafka es la siguiente:

estructura

Los productores y consumidores de Kafka están conectados a través del protocolo TCP.

productor : El productor también es nuestra aplicación, u otros programas para ser enviados, es responsable de enviar mensajes topica partition,

consumidor : consumidor, representado por el grupo de consumidores, el grupo de consumidores puede considerarse como un consumidor, el consumidor se suscribe a un tema, luego Kafka enviará el mensaje al grupo de consumidores, en este momento, el grupo de consumidores cargará el saldo El mensaje se distribuye uniformemente a todas las instancias de consumidor del grupo.

tema : tema (tema de datos), el lugar donde se almacenan los registros de datos y los datos comerciales se pueden distinguir a través de él. Un tema puede tener una o más suscripciones de consumidores

partición : partición, cada tema tendrá una o más particiones, y la partición es para dividir los datos recibidos por el tema en diferentes particiones de acuerdo con las reglas de partición y partición especificadas. Cuando los consumidores se suscriben a los mensajes de consumo de temas, pueden especificar una partición o no. Si no se especifica, Kafka utilizará el sondeo para enviar los datos de todas las particiones al consumidor; por supuesto, la partición especificada solo enviará los mensajes de la partición especificada. El punto también es obvio que los mensajes en la misma partición están ordenados.

(Descripción del sitio web oficial: para cada tema, el clúster de kafka mantendrá un registro de partición, y los datos de cada partición están en orden y se adjuntan continuamente al archivo de registro de confirmación. A cada registro en la partición se le asignará un número de identificación para indicar el orden, que también puede llamarse offset (desplazamiento), es decir, los consumidores pueden obtener registros a través de este desplazamiento, que se puede obtener de una ubicación específica.

La capacidad de almacenamiento de una partición está limitada por el límite de archivos del host, pero un tema puede tener varias particiones. En un clúster, si un tema está en un nodo de clúster, la partición también se sincronizará con el tema de otros nodos para mantener la tolerancia a fallas)

replicación : copia, cada partición tiene un líder, 0 o más seguidores, el líder solo hace escritura exclusiva y el seguidor solo respalda, cuando el líder cae, se elegirá un líder entre los seguidores restantes.

Nota: Al crear un tema, la cantidad de réplicas no puede ser mayor que la cantidad de intermediarios, es decir, la cantidad de nodos de Kafka, porque la réplica está sincronizada con otros nodos, por lo que si es mayor que los datos del nodo, no puede ser creado.

corredor : servicio kafka

Clúster : Debajo del clúster, siempre habrá un nodo como nodo leader, cero o más nodos follwers, solo leaderel nodo maneja todas las solicitudes de lectura y escritura, y otros nodos son pasivos para leaderlograr la sincronización de datos. Si estos leadernodos están inactivos, uno de ellos será follwerselegido nuevo leader.

Sistema de mensajes : en comparación con otros modos de sistema de mensajes (con 队列y 发布-订阅dos módulos), en el modo de cola de kafka, el consumidor es un grupo de consumidores, como redis, el modo de cola solo puede tener un consumidor y el consumo desaparecerá; publicar-suscribir modo, otro middleware también es modo de suscripción múltiple, la suscripción kafka es por tema, la cantidad de instancias de consumidores en todos los grupos de consumidores no puede ser mayor que la cantidad de particiones.

Procesamiento de secuencias : Kafka tiene la función de procesamiento de secuencias. Continuamente obtendrá datos del tema y luego realizará el procesamiento de datos. Puede agregar datos, unirse y otros procesamientos complejos, y luego escribir en el tema.

Instalar

Dirección oficial: Kafka Chinese Documentation-ApacheCN

La dirección de descarga oficial, la descarga es muy rápida.

puesta en marcha

método uno

Kafka usa zookeeper para la administración de clústeres, por lo que necesita un servidor zookeeper. Kafka proporciona zookeeper, que se puede usar directamente

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

Todavía es un poco diferente de zookeeper.La secuencia de comandos de kafka es una secuencia de comandos de inicio, y la secuencia de comandos de zookeeper es una línea de comando.

empezar kafka

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

forma dos

En lugar de usar el guardián del zoológico que viene con kafka, use el clúster del guardián del zoológico que construimos antes

vi config/servidor.propiedades

/guardián del zoológico

#Modificar la configuración a la dirección del clúster de zookeeper

zookeeper.connect=localhost:2181,localhost:2182,localhost:2183

puesta en marcha

./bin/zkServer.sh iniciar zoo.cfg

./bin/zkServer.sh iniciar zoo2.cfg

./bin/zkServer.sh iniciar zoo3.cfg

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

configuración

Descripción de los elementos de configuración: documentación china de Kafka - ApacheCN

operación de comando

Kafka trae muchos comandos, y usamos estos comandos para crear temas, enviar mensajes y consumir mensajes.

imagen-20230103221311638

crear tema

./bin/kafka-topics.sh --zookeeper localhost:2181 --create --topic test_topic --particiones 3 --factor de replicación 3

–zookeeper: especifica la dirección del zookeeper

–particiones: cuántos fragmentos de tema

–factor de replicación: factor de replicación, controla el número de copias de datos escritas, este valor es <= número de intermediarios, aquí soy independiente, así que aquí hay 1

Ver lista de temas

./bin/kafka-topics.sh --list --zookeeper localhost:2181

enviar un mensaje (iniciar un productor)

#Conexión larga

./bin/kafka-console-producer.sh --broker-list 192.168.17.128:9092 --topic test_topic

El cliente recibe un mensaje que indica el éxito

Consumir mensajes (iniciar un consumidor)

#Conexión larga

./bin/kafka-console-consumer.sh --bootstrap-server 192.168.17.128:9092 --topic test_topic

Envía un pequeño mensaje al cliente productor, si se puede recibir aquí, ya es exitoso

Información del tema de consulta

./bin/kafka-topics.sh --describe --zookeeper localhost:2181 --topic test_topic

imagen-20230211143956872

Aunque el concepto se ha explicado anteriormente, todavía se menciona aquí.

**tema:** nombre del tema, porque se especifican 3 particiones y 3 distribuciones, así que aquí hay 3 datos;

**Partición: **Partición, que indica en qué nodo se encuentra la partición actual. Cada tema tendrá una o más particiones, y los datos almacenados en cada partición son diferentes (los datos sobre el tema se distribuyen uniformemente)

**Líder y réplicas: **Información de réplica, los datos de cada partición realizarán una copia de seguridad de una cantidad específica de copias para garantizar capacidades de recuperación ante desastres, cada partición tiene un líder, 0 o más seguidores, el líder solo escribe solo y el seguidor solo hace copia de seguridad, cuando el líder de una partición cae, los seguidores restantes elegirán un líder, como se muestra en la figura de arriba Replicas: 1,2,3,

imagen-20230211152324585

Si el líder 1 se desconecta, los 2 y 3 restantes elegirán a uno de ellos como líder.

Entonces, aquí Leaderestá el nodo maestro de la copia de la partición, que es responsable de toda la lectura y escritura, y Replicases la información donde se encuentra la distribución.

Ahora mata un nodo kafka:

imagen-20230211144054008

Eliminó con éxito 1 y eligió un nuevo líder

imagen-20230211144146960

Aviso:

  1. Como se mencionó anteriormente, la cantidad de réplicas no puede ser mayor que la cantidad de nodos de Kafka. Aquí, la cantidad de nodos es suficiente. Sin embargo, factores de fuerza mayor durante el proceso de operación hicieron que el clúster eliminara activamente los nodos que detectaron anomalías.
  2. Este comando puede ver la información del tema y también se usa como un comando para verificar el estado del clúster en Kafka. No hay un comando similar en Kafka zkServer.sh status, por lo que puede usar este comando para verificar si alguna partición está fuera de línea.

borrar tema

Esto debe server.propertiesconfigurarse en: delete.topic.enable=true, de lo contrario, este tema solo se marcará como eliminado y no se eliminará.

./bin/kafka-topics.sh --delete --zookeeper localhost:2181 --topic test_topic

imagen-20230206222944176

grupo

El sitio web oficial de kafka proporciona un ejemplo de configuración. Podemos agregar la configuración de acuerdo con él. Solo hay 3 lugares diferentes en la configuración del clúster. Debido a que estoy implementando en un servidor, necesito distinguir otros servicios.

  • registro.dir
  • corredor.id
  • oyentes (tenga en cuenta la configuración de la dirección ip aquí)

Ejemplo de configuración simple de Zookeeper

# ZooKeeper服务地址
zookeeper.connect=localhost:2181,localhost:2182,localhost:2183
# topic分区日志数
num.partitions=8
# 自动创建topic的默认副本数
default.replication.factor=3
# 自动创建topic
auto.create.topics.enable=false
# 指定写入成功的副本数,当写入数据的副本数达不到这个值,则会报错
min.insync.replicas=2
delete.topic.enable=true

# 集群配置
# 日志保存目录
log.dir=./log1
# broker服务ID
broker.id=1
# 监听地址
listeners=PLAINTEXT://192.168.17.128:9092

Determine si el estado del clúster es correcto:

./bin/kafka-topics.sh --describe --zookeeper localhost:2181 --topic test_topic

cerrar

El apagado y la falla son diferentes, el apagado normal, Kafka ejecutará:

  1. Sincronice todos los registros en el disco, lo que puede evitar el proceso de registro de recuperación al reiniciar y puede mejorar la velocidad de inicio;
  2. Cuando se apaga el líder, las particiones en el líder se migrarán a otras réplicas, y cambiar el líder es más rápido;

usar

  1. Primero asegúrese de que el puerto del firewall del servidor esté abierto

    firewall-cmd --add-port=9200/tcp --permanent
    
  2. Kafka requiere dependencias de inicio de sesión

     <dependency>
                <groupId>org.apache.kafka</groupId>
                <artifactId>kafka-clients</artifactId>
                <version>2.8.0</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.13.1</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.33</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>1.2.10</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>1.2.10</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-access</artifactId>
                <version>1.2.3</version>
            </dependency>
    

    inicio de sesión.xml

    <!-- 级别从高到低 OFF 、 FATAL 、 ERROR 、 WARN 、 INFO 、 DEBUG 、 TRACE 、 ALL -->
    <!-- 日志输出规则 根据当前ROOT 级别,日志输出时,级别高于root默认的级别时 会输出 -->
    <!-- 以下 每个配置的 filter 是过滤掉输出文件里面,会出现高级别文件,依然出现低级别的日志信息,通过filter 过滤只记录本级别的日志 -->
    <!-- scan 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。 -->
    <!-- scanPeriod 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
    <!-- debug 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
    <configuration scan="true" scanPeriod="60 seconds" debug="false">
        <!-- 动态日志级别 -->
        <jmxConfigurator />
        <!-- 定义日志文件 输出位置 -->
        <!-- <property name="log_dir" value="C:/test" />-->
        <property name="log_dir" value="./logs" />
        <!-- 日志最大的历史 30天 -->
        <property name="maxHistory" value="30" />
    
        <!-- ConsoleAppender 控制台输出日志 -->
        <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>
                    <!-- 设置日志输出格式 -->
                    %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n
                </pattern>
            </encoder>
        </appender>
    
        <!-- ERROR级别日志 -->
        <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 RollingFileAppender -->
        <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!-- 过滤器,只记录WARN级别的日志 -->
            <!-- 果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志。 -->
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <!-- 设置过滤级别 -->
                <level>ERROR</level>
                <!-- 用于配置符合过滤条件的操作 -->
                <onMatch>ACCEPT</onMatch>
                <!-- 用于配置不符合过滤条件的操作 -->
                <onMismatch>DENY</onMismatch>
            </filter>
            <!-- 最常用的滚动策略,它根据时间来制定滚动策略.既负责滚动也负责出发滚动 -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!--日志输出位置 可相对、和绝对路径 -->
                <fileNamePattern>
                    ${log_dir}/error/%d{yyyy-MM-dd}/error-log.log
                </fileNamePattern>
                <!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>是6, 则只保存最近6个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除 -->
                <maxHistory>${maxHistory}</maxHistory>
            </rollingPolicy>
            <encoder>
                <pattern>
                    <!-- 设置日志输出格式 -->
                    %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n
                </pattern>
            </encoder>
        </appender>
    
        <!-- WARN级别日志 appender -->
        <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!-- 过滤器,只记录WARN级别的日志 -->
            <!-- 果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志。 -->
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <!-- 设置过滤级别 -->
                <level>WARN</level>
                <!-- 用于配置符合过滤条件的操作 -->
                <onMatch>ACCEPT</onMatch>
                <!-- 用于配置不符合过滤条件的操作 -->
                <onMismatch>DENY</onMismatch>
            </filter>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!--日志输出位置 可相对、和绝对路径 -->
                <fileNamePattern>${log_dir}/warn/%d{yyyy-MM-dd}/warn-log.log</fileNamePattern>
                <maxHistory>${maxHistory}</maxHistory>
            </rollingPolicy>
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
            </encoder>
        </appender>
    
        <!-- INFO级别日志 appender -->
        <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>INFO</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${log_dir}/info/%d{yyyy-MM-dd}/info-log.log</fileNamePattern>
                <maxHistory>${maxHistory}</maxHistory>
            </rollingPolicy>
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
            </encoder>
        </appender>
    
        <!-- DEBUG级别日志 appender -->
        <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>DEBUG</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${log_dir}/debug/%d{yyyy-MM-dd}/debug-log.log</fileNamePattern>
                <maxHistory>${maxHistory}</maxHistory>
            </rollingPolicy>
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
            </encoder>
        </appender>
    
        <!-- TRACE级别日志 appender -->
        <appender name="TRACE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>TRACE</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${log_dir}/trace/%d{yyyy-MM-dd}/trace-log.log</fileNamePattern>
                <maxHistory>${maxHistory}</maxHistory>
            </rollingPolicy>
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
            </encoder>
        </appender>
    
        <!-- root级别 DEBUG -->
        <root>
            <!-- 打印debug级别日志及以上级别日志 -->
            <level value="info" />
            <!-- 控制台输出 -->
            <appender-ref ref="console" />
            <!-- 文件输出 -->
            <appender-ref ref="ERROR" />
            <appender-ref ref="INFO" />
            <appender-ref ref="WARN" />
            <appender-ref ref="DEBUG" />
            <appender-ref ref="TRACE" />
        </root>
    </configuration>
    
    

informar error

  1. error de conexión
org.apache.kafka.common.network.Selector - [Consumer clientId=con, groupId=con-group] Connection with /192.168.17.128 disconnected
java.net.ConnectException: Connection refused: no further information

org.apache.kafka.clients.NetworkClient - [Consumer clientId=con, groupId=con-group] Connection to node -1 (/192.168.17.128:9092) could not be established. Broker may not be available.

La razón más probable es que listenersla configuración no configura la ip, puedes intentar cambiarla primero, estoy aquí porque no hay configuración de la IP, finalmente se cambia listeners=PLAINTEXT://192.168.17.128:9092y luego el error del consumidor desaparece.

  1. El siguiente es el error del productor:
Error while fetching metadata with correlation id 53 : {
    
    test_topic=UNKNOWN_TOPIC_OR_PARTITION}

Parece un tema desconocido. Creo que el sitio web oficial es VERDADERO por defecto.

imagen-20230110221509106

En la configuración final se añade otra frase, auto.create.topics.enable=truela configuración completa es la siguiente:

# ZooKeeper服务地址
zookeeper.connect=localhost:2181,localhost:2182,localhost:2183
# topic分区日志数
num.partitions=2
# 自动创建topic的默认副本数
default.replication.factor=3
# 自动创建topic
auto.create.topics.enable=false
# 指定写入成功的副本数,当写入数据的副本数达不到这个值,则会报错
min.insync.replicas=2
# 设置自动创建topic
auto.create.topics.enable=true
delete.topic.enable=true

#集群配置
# 日志保存目录
log.dir=./log1
# broker服务ID
broker.id=1
# 监听地址
listeners=PLAINTEXT://192.168.17.128:9092

despues de eso es normal

Obtenga un script de inicio con un solo clic:

/data/kafka/kafka_2.11-1.0.0/bin/kafka-server-start.sh -daemon /data/kafka/kafka_2.11-1.0.0/config/server.properties

/data/kafka/kafka_2.11-1.0.0/bin/kafka-server-start.sh -daemon /data/kafka/kafka_2.11-1.0.0/config/server2.properties

/data/kafka/kafka_2.11-1.0.0/bin/kafka-server-start.sh -daemon /data/kafka/kafka_2.11-1.0.0/config/server3.properties

sleep 3

echo 'kafka启动完成'

ejemplo de conexion java

Código de consumo:

Aquí hay varias configuraciones requeridas, correspondientes a los parámetros en el comando de shell

bootstrap.servers - dirección del servidor Kafka

cliente.id - id del cliente

key.deserializer - configuración del deserializador de claves

value.deserializer - configuración de deserialización de valor

group.id - ID de grupo de consumidores

auto.offset.reset - método de compensación

    public static void consumer() {
    
    
        Properties properties = new Properties();
        // 必填参数
        // kafka服务地址
        properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, IP);
        // 客户端消费者ID
        properties.put(ConsumerConfig.CLIENT_ID_CONFIG, "con");
        // key序列化器
        properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
        // value序列化器
        properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
        // 消费者组ID,如果需要重新读取,可以切换groupId为新的ID就可以了,然后设置自动提交为true
        properties.put(ConsumerConfig.GROUP_ID_CONFIG, "con-group");
            // 消费偏移量
        // earliest:分区中有offset时,从offset位置消费,没有从头消费
        // latest:分区中有offset时,从offset位置下佛,没有时,消费新产生的
        // none:分区有offset时,从offset后开始消费,如果有一个分区缺少已提交的offset时,抛异常
        properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");

        // 回话超时时间
        properties.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, 6000);
        // 心跳间隔
        properties.put(ConsumerConfig.HEARTBEAT_INTERVAL_MS_CONFIG, "2000");
        // 自动提交间隔
        properties.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");
        // 每次拉取的最大数据量
        properties.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 2);
        // 如果需要重复消费,可以设置自动提交为FALSE,这样每次拉取都是从之前的offset开始拉取
        properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
    

        new Thread(() -> {
    
    
            while (true) {
    
    
                try(KafkaConsumer<String, Object> con = new KafkaConsumer<>(properties);){
    
    
                    con.subscribe(Collections.singleton(TOPIC));
                    ConsumerRecords<String, Object> poll = con.poll(Duration.ofSeconds(5000));
                    for (ConsumerRecord<String, Object> record : poll) {
    
    
                        System.out.println("topic:" + record.topic() + ",offset:" + record.offset() + ",数据:" + record.value().toString());
                    }
                }
            }
        }).start();
    }

Código del productor:

es también un parámetro requerido

bootstrap.servidores

Identificación del cliente

key.deserializer - configuración del número de serie de la clave

value.deserializer - configuración del número de serie del valor

public static void producer() {
    
    
        Properties properties = new Properties();
        // 必要条件
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, IP);
        properties.put(ProducerConfig.CLIENT_ID_CONFIG, "pro");
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        KafkaProducer<String, String> pro = new KafkaProducer<>(properties);

        new Thread(() ->{
    
    
            while (true) {
    
    
                try {
    
    
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
    
    
                    throw new RuntimeException(e);
                }
                Future<RecordMetadata> result = pro.send(new ProducerRecord<>(TOPIC, "1","dddd"), (meta, error) -> {
    
    
                    if (error != null) {
    
    
                        error.printStackTrace();
                        return;
                    }
                    System.out.println("发送回调:" + meta.toString());
                });
                System.out.println("发送的结果:" + result );
            }
        }).start();

    }

Observación:

  1. Kafka agrupará automáticamente los grandes datos en grupos de consumidores y, al mismo tiempo, también se puede configurar en el cliente max.poll.records(ConsumerConfig.MAX_POLL_RECORDS_CONFIG)para controlar la cantidad de datos extraídos cada vez;

    Debido a que se extrae del grupo de consumidores, varios clientes pueden establecer el mismo ID de grupo para suscribirse al mismo tema;

  2. Si es necesario consumir datos de manera ordenada, también es necesario asegurarse de que los mensajes del productor se envíen a una partición, y el mecanismo de partición de Kafka se puede utilizar para el consumo secuencial;

  3. Si necesita extraer todos los datos, puede configurar el ID de grupo y la cantidad de datos en lotes, y enviarlos automáticamente a verdadero, k

        // 消费者组ID,如果需要重新读取,可以切换groupId为新的ID就可以了,然后设置自动提交为true
        properties.put(ConsumerConfig.GROUP_ID_CONFIG, "con-group");
        // 每次拉取的最大数据量
        properties.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 2000);
        // 如果需要重复消费,可以设置自动提交为FALSE,这样每次拉取都是从之前的offset开始拉取
        properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true);
        // 消费偏移量

Supongo que te gusta

Origin blog.csdn.net/qq_28911061/article/details/128985197
Recomendado
Clasificación