Cobertura de publicación

La latencia de cola alta cuando se publican mensajes puede deberse a retrasos transitorios de la red o a una lentitud temporal del servidor. La cobertura de publicación permite que un cliente publicador de Pub/Sub envíe una solicitud de publicación de respaldo (cobertura) en paralelo si una solicitud en curso no se completa dentro de un retraso configurado, usando la respuesta que se devuelva primero.

En este documento, se proporciona información sobre el uso de la cobertura de publicación con mensajes publicados en un tema.

Antes de comenzar

Antes de configurar el flujo de trabajo de publicación, asegúrate de haber completado las siguientes tareas:

Roles obligatorios

Para obtener los permisos que necesitas para enviar solicitudes de publicación de cobertura a un tema, pídele a tu administrador que te otorgue el rol de IAM de Publicador de Pub/Sub (roles/pubsub.publisher) en el tema. Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.

También puedes obtener los permisos necesarios a través de roles personalizados o cualquier otro rol predefinido.

Necesitas permisos adicionales para crear o actualizar temas y suscripciones.

Acerca de la cobertura de publicación

La configuración de cobertura controla cómo y cuándo las bibliotecas cliente de Pub/Sub envían solicitudes de publicación de cobertura. La cobertura de publicación está inhabilitada de forma predeterminada. Cuando se habilitan, las bibliotecas cliente tienen la siguiente configuración de cobertura:

  • Retraso de cobertura: Es la cantidad de tiempo que espera una biblioteca cliente antes de enviar una solicitud de publicación adicional en paralelo si la solicitud anterior no se completó. El valor predeterminado es 1 segundo, y el valor configurado debe ser entre 100 milisegundos y 10 segundos.
  • Cantidad máxima de tokens: Es la cantidad máxima de tokens que una biblioteca cliente puede acumular para enviar solicitudes de publicación protegidas. Cada solicitud de publicación protegida consume 1 token. El valor predeterminado es 50, y el valor configurado debe estar entre 1 y 250.
  • Proporción de recarga: Es la cantidad de tokens que se agregan para cada solicitud de publicación correcta. Este valor controla la fracción máxima de solicitudes de publicación que se pueden cubrir con el tiempo. Por ejemplo, un coeficiente de reabastecimiento de 0.1 permite que se cubra hasta el 10% de las solicitudes de publicación. El valor predeterminado es 0.1, y el valor configurado debe estar entre 0.001 y 0.2.

Para proteger las solicitudes de publicación, la demora de protección debe ser más corta que el tiempo de espera de la solicitud inicial y el tiempo de espera total en la configuración de reintentos del publicador. De lo contrario, el cliente publicador no se inicializará. Cuando se habilita la cobertura de publicación, la biblioteca cliente envía solicitudes de publicación de la siguiente manera:

  • Si una solicitud de publicación en curso no se completa dentro de la demora de cobertura y hay al menos un token disponible, la biblioteca cliente consume un token y envía una solicitud de publicación adicional para el mismo lote de mensajes en paralelo, mientras mantiene pendiente la solicitud inicial.
  • Si ninguna de las solicitudes en curso se completa después de otro retraso de cobertura, la biblioteca cliente sigue enviando solicitudes de cobertura adicionales en intervalos del retraso de cobertura mientras los tokens sigan disponibles y no haya vencido el tiempo de espera total.
  • En cuanto se completa correctamente cualquier solicitud de publicación en curso para el lote, la biblioteca cliente completa la operación de publicación, cancela los intentos en curso restantes para ese lote y aumenta los tokens disponibles según la proporción de recarga, hasta el máximo de tokens.

Cómo proteger una solicitud de publicación

A diferencia de las solicitudes de reintento, que esperan a que falle o se agote el tiempo de espera de una solicitud de publicación en curso, la cobertura de publicación mantiene la solicitud inicial pendiente mientras envía una solicitud de cobertura simultánea. Esto reduce la latencia de cola sin cancelar de forma prematura las solicitudes que están a punto de tener éxito.

Debido a que varias solicitudes para el mismo lote de mensajes pueden estar en curso simultáneamente, es posible que más de un intento tenga éxito antes de que se cancelen los intentos restantes, ya que la cancelación de la solicitud de publicación se realiza de la mejor manera posible. Como resultado, es posible que recibas mensajes duplicados con diferentes IDs de mensaje, lo que puede aumentar el tráfico de red del cliente y los costos de Pub/Sub por publicar y entregar esos duplicados. Consulta "Soluciona problemas de mensajes duplicados, reenviados o faltantes" para obtener sugerencias sobre cómo controlar los mensajes duplicados.

Si una degradación del servicio provoca un aumento sostenido de la latencia o los errores, la configuración de tokens máximos y de proporción de recarga evita que las tasas de publicación de cobertura sean demasiado altas. Debido a que los tokens solo se agregan cuando las solicitudes de publicación se realizan correctamente, la lentitud o los errores sostenidos agotan rápidamente los tokens disponibles y limitan automáticamente las solicitudes de cobertura.

En este código de muestra, se indica cómo crear un publicador con una configuración de cobertura personalizada. No todas las bibliotecas cliente admiten la cobertura de publicación. Consulta la documentación de referencia de la API para el lenguaje que elijas.

Java

Antes de probar esta muestra, sigue las instrucciones de configuración de Java en la guía de inicio rápido sobre el uso de bibliotecas cliente. Si quieres obtener más información, consulta la documentación de referencia de la API de Pub/Sub para Java.


import com.google.api.core.ApiFuture;
import com.google.cloud.pubsub.v1.HedgingSettings;
import com.google.cloud.pubsub.v1.Publisher;
import com.google.protobuf.ByteString;
import com.google.pubsub.v1.PubsubMessage;
import com.google.pubsub.v1.TopicName;
import java.io.IOException;
import java.time.Duration;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class PublishWithHedgingSettingsExample {
  public static void main(String... args) throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String topicId = "your-topic-id";

    publishWithHedgingSettingsExample(projectId, topicId);
  }

  public static void publishWithHedgingSettingsExample(String projectId, String topicId)
      throws IOException, ExecutionException, InterruptedException {
    TopicName topicName = TopicName.of(projectId, topicId);
    Publisher publisher = null;

    try {
      // Hedging settings configures how and when the publisher sends multiple concurrent publish
      // requests to reduce tail latency.
      Duration hedgeDelay = Duration.ofMillis(500); // default: 1000 ms (1 second)
      int maxTokens = 100; // default: 50
      float refillRatio = 0.05f; // default: 0.1

      HedgingSettings hedgingSettings =
          HedgingSettings.newBuilder()
              .setHedgeDelay(hedgeDelay)
              .setMaxTokens(maxTokens)
              .setRefillRatio(refillRatio)
              .build();

      // Create a publisher instance with hedging settings bound to the topic
      publisher = Publisher.newBuilder(topicName).setHedgingSettings(hedgingSettings).build();

      String message = "Hello world!";
      ByteString data = ByteString.copyFromUtf8(message);
      PubsubMessage pubsubMessage = PubsubMessage.newBuilder().setData(data).build();

      // Once published, returns a server-assigned message id (unique within the topic)
      ApiFuture<String> messageIdFuture = publisher.publish(pubsubMessage);
      String messageId = messageIdFuture.get();
      System.out.println("Published a message with hedging settings: " + messageId);

    } finally {
      if (publisher != null) {
        // When finished with the publisher, shutdown to free up resources.
        publisher.shutdown();
        publisher.awaitTermination(1, TimeUnit.MINUTES);
      }
    }
  }
}

Cobertura de publicación con claves de ordenamiento

La cobertura de publicación no se puede usar con el orden de mensajes. Debido a que la cobertura de publicación envía solicitudes de publicación simultáneas para el mismo lote de mensajes, el servicio de Pub/Sub podría recibir y procesar esas solicitudes de forma desordenada. Si habilitas el orden de los mensajes y la cobertura de publicación en un cliente publicador, la creación del publicador fallará con un error.

Sugerencias y prácticas recomendadas

Ten en cuenta las siguientes prácticas recomendadas cuando configures la cobertura de publicación:

  • Usa la cobertura para la latencia de cola transitoria: La cobertura de publicación está diseñada para suavizar los aumentos repentinos de latencia de corta duración causados por retrasos temporales de la red o lentitud breve del servidor. No dependas de la cobertura para mitigar interrupciones prolongadas o errores persistentes.
  • Cobertura con políticas de reintento: Establece un tiempo de espera de solicitud inicial más largo en tu configuración de reintentos junto con un retraso de cobertura más corto. Los tiempos de espera cortos y agresivos cancelan las solicitudes de forma prematura y activan reintentos completos, lo que descarta el trabajo que ya está en curso en el servidor. Un tiempo de espera más largo permite que se complete la solicitud original si solo se retrasa un poco.
  • Control de flujo y cobertura del cliente: La cobertura de publicación no resuelve los retrasos del cliente, como la contención de CPU o la falta de subprocesos. Si la latencia de publicación alta se debe a que los mensajes se ponen en cola en la memoria del cliente, usar el control de flujo para administrar los tamaños de las colas puede ayudar, aunque también se deben abordar las restricciones de recursos del host.
  • Supervisa las métricas de latencia y capacidad de procesamiento de publicación: Usa gráficos de métricas de Monitoring, como topic/send_request_latencies, para identificar aumentos repentinos de latencia de cola y determinar si la cobertura puede ayudar. Las tasas altas de errores CANCELLED pueden indicar que los plazos de solicitud están configurados con un valor demasiado bajo. Cuando se ajusta de manera eficaz, la cobertura de publicación mantiene la capacidad de procesamiento de mensajes y el costo de bytes del tema aproximadamente constantes, incluso durante la latencia de cola de publicación.

¿Qué sigue?

Para obtener información sobre cómo configurar las opciones de publicación avanzadas, consulta lo siguiente: