Cuando no se pueden aumentar las particiones de Kafka, utilice subprocesos múltiples para mejorar la capacidad de consumo de Kafka (código fuente adjunto)

Hace dos días, csdn me recordó que tenía otro fan, lo que estimuló mi motivación para escribir. No hagas clic para ver el número de mis fanáticos, ¡jaja!      

En circunstancias normales, los datos del hilo del consumidor de Kafka se particionan (patición) uno a uno, y una sola patición es la unidad más pequeña de la operación en paralelo de Kafka. Kafka solo permite que un hilo consumidor consuma los datos de una sola partición. Por ejemplo, hacemos 20 particiones. De hecho En correspondencia con 20 hilos de consumidores, cuando realizamos algunas actividades, habrá un fuerte aumento en la cantidad de mensajes, nuestros hilos de consumidores son limitados y la capacidad de procesar mensajes puede no mantenerse al día, lo que da como resultado una gran cantidad de mensajes que no se pueden procesar. .

En este momento, es posible que necesitemos optimizar y aumentar la capacidad de procesamiento. La mayoría de la gente puede pensar en agregar particiones. Las particiones se pueden aumentar, pero es imposible aumentar infinitamente hacia arriba. Aquí utilizamos una solución multiproceso.

package com.imcbb;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Service;

import java.util.concurrent.*;

/**
 * @author kevin
 * Date 2020-09-24
 * Time 09:43
 */
@Service
public class KafkaConsumer {
    private static Logger logger = LoggerFactory.getLogger(KafkaConsumer.class);


    ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 3, 10, TimeUnit.SECONDS,
            new SynchronousQueue<>(),
            new ThreadFactoryBuilder().setNameFormat("KThread-%d").build(),
            (r, executor) -> {
                logger.warn("Ops,Rejected!");
                try {
                    executor.getQueue().put(r);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
//                        new ThreadPoolExecutor.CallerRunsPolicy()

    );

    @KafkaListener(topics = "myTopic")
    public void listen(ConsumerRecord<?, ?> cr) {

        executor.execute(() -> {
            logger.info("---------" + cr.toString());
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

    }
}

En el código anterior, hemos creado un grupo de subprocesos para consumir mensajes de una partición. Aquí hay dos puntos que necesitan especial atención:

1. La cola para almacenar tareas en el grupo de subprocesos. Aquí usamos la cola de bloqueo SynchronousQueue. Esta cola es muy interesante. Es una cola sin capacidad. Si está interesado, por favor revise Internet y no dé demasiada explicación. Se usa SynchronousQueue porque, si Para evitar la pérdida de mensajes acumulados en la cola cuando el sistema está inactivo anormalmente o la aplicación se reinicia (por supuesto, esto no puede evitar por completo que el hilo se cuelgue debido a una excepción en el sistema durante el trabajo del hilo. Si se requiere una mayor disponibilidad, considere almacenarlo en la base de datos primero. En redis, haz el mecanismo de procesamiento de compensación).

2. Cuando hay demasiados mensajes y el grupo de subprocesos está demasiado ocupado, tenemos dos soluciones aquí

2.1 Bloquear el hilo del consumidor que escucha y usar el nuevo ThreadPoolExecutor.CallerRunsPolicy (), en este momento el mensaje ya no se consumirá

2.1 Personaliza la estrategia de rechazo y devuelve la tarea

(r, executor) -> {
    logger.warn("Ops,Rejected!");
    try {
        executor.getQueue().put(r);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

}

Las dos soluciones anteriores pueden resolver el problema, simplemente elija una para usar, ninguna de las dos soluciones garantiza el orden de procesamiento de los mensajes.

Una ventaja de utilizar el segundo tipo es que se puede comprobar la capacidad de consumo del consumidor a través del registro, y ver si hay algún rechazo, para ajustar el número de hilos de forma adecuada.

Lo anterior es el método de consumo multiproceso, que ha sido probado en nuestro entorno de producción, ¡jaja!

El artículo simplemente publicó un código y escribió una demostración completa para todos, puede descargarlo como referencia: https://github.com/kevinmails/kafka-consumer-demo

El requisito previo es instalar kafka en esta máquina. El manual de instalación oficial (la versión más pequeña disponible, las pruebas locales son suficientes), si no puede entender el mensaje oficial, déjeme un mensaje y escribiré otro artículo de instalación. Hay un manual de instalación oficial: https://kafka.apache.org/quickstart

¡Espero que todos tengan que ayudar!

Referencia: https://www.confluent.io/blog/how-choose-number-topics-partitions-kafka-cluster/

 

 

 

Supongo que te gusta

Origin blog.csdn.net/kevin_mails/article/details/108750743
Recomendado
Clasificación