Tiempo de envío de compensación de Spring Kafka

1. premisa

En el proyecto se usa la versión spring-kafka1.3 y también se usa la versión 2.5. Sin embargo, el momento de enviar la compensación es vago, y esta vez se aclara aún más a través del análisis y los datos del código fuente.

2. Conoce el offset de KafkaConsumer

KafkaConsumer es una entrada del cliente de Kafka. A través de KafkaConsumer, se pueden extraer datos en el servicio de Kafka, se pueden enviar paquetes de latidos y se puede informar el desplazamiento (desplazamiento) de la partición de consumo.

Para garantizar que los registros que no hayan sido leídos por los consumidores siempre puedan devolverse al llamar al método KafkaConsumer.poll(), los consumidores deben mantener el desplazamiento de desplazamiento correspondiente a los mensajes leídos en cada partición y enviar el desplazamiento a Kafka por teléfono móvil o regularmente El servidor, para que el mensaje no se pierda.

Hay dos categorías principales para enviar compensaciones, una es automática y la otra es manual. Controlado por el parámetro enable.auto.commit.

Cuando =true, combinado con el parámetro auto.commit.interval.ms, el consumidor verificará si se debe enviar la compensación cada vez que realice una encuesta y enviará automáticamente la compensación devuelta por la última encuesta.

Cuando = falso, el desarrollador debe enviar la compensación manualmente, consulte el siguiente código:

  Properties properties = new Properties();
  properties.setProperty("bootstrap.servers", "10.74.20.54:9092");
  properties.setProperty("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
  properties.setProperty("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
  properties.setProperty("enable.auto.commit", "false"); // 禁止自动提交
  properties.setProperty("group.id", "my-group"); // 

  KafkaConsumer<String, String> consumer = new KafkaConsumer<>(properties);
  consumer.subscribe(Collections.singletonList("topic")); // 订阅主题
  try {
      while (! Thread.currentThread().isInterrupted()) {
          ConsumerRecords<String, String> records = consumer.poll(1000);
          records.forEach(System.out::println);
          consumer.commitAsync(); // 异步提交偏移量
      }
  } catch (WakeupException ignore) {
      // 忽略关闭异常
  } finally {
      try {
          consumer.commitSync(); // 同步提交偏移量
      } finally {
          consumer.close();
      }
  }

Aquí se divide en envío asincrónico o envío sincrónico:

Envío síncrono: el uso de KafkaConsumer.commitSync() enviará la última compensación y esperará a que el corredor responda a la solicitud de envío. Reintentar continuamente hasta que se encuentre una confirmación exitosa o un error irrecuperable hará que la aplicación permanezca bloqueada, lo que limitará el rendimiento de la aplicación.

Envío asincrónico: el uso de KafkaConsumer.commitAsync() enviará la última compensación sin esperar la respuesta del corredor y sin volver a intentarlo. No se realiza ningún reintento porque puede haber un desplazamiento mayor que se haya enviado correctamente y el reintento puede sobrescribir el valor más reciente, lo que da como resultado mensajes duplicados después del reequilibrio. Este método ejecuta una devolución de llamada especificada por el usuario cuando el intermediario responde. Las devoluciones de llamada se utilizan a menudo para registrar errores de confirmación o generar métricas. Sin embargo, si desea volver a intentarlo, debe prestar atención al orden de presentación.

Desde la perspectiva del rendimiento: adopte la forma del código anterior, asíncrono + síncrono

3. Implementación de Spring-kafka

Después de spring-kafka 2.3, enable.auto.commit se establece en falso de forma predeterminada (verdadero antes de esta versión) y AckMode se establece de forma predeterminada en lote. Al establecer el valor en falso, kafkaConsumer ya no envía automáticamente la compensación (compensación). En su lugar, use la primavera para ayudarnos a lograrlo.

Que sping es cómo lograr? En la siguiente figura, podemos ver que KafkaMessageListenerContainer.run() implementa un ciclo while internamente y luego llama a pollAndInvoke() para completar la lectura de datos. En la parte superior del método pollAndInvoke, se juzga si se trata de un envío manual, y si es así, envíe la última vez El desplazamiento para leer.

 

Supongo que te gusta

Origin blog.csdn.net/lzzyok/article/details/124788556
Recomendado
Clasificación