En esta página, se explica cómo recibir y confirmar mensajes con la función de Pub/Sub de entrega “exactamente una vez”, que te permite hacer un seguimiento de los mensajes y evitar su procesamiento duplicado. Cuando la función está habilitada, Pub/Sub proporciona la siguiente semántica:
Los suscriptores pueden determinar si las confirmaciones de recepción de mensajes se realizaron correctamente.
No se vuelve a realizar la entrega después de que se confirma correctamente el mensaje.
No se vuelve a realizar la entrega mientras un mensaje está pendiente. Un mensaje se considera pendiente hasta que vence el plazo de confirmación o se confirma el mensaje.
En caso de que se realicen varias entregas válidas debido al vencimiento del plazo de confirmación o a la confirmación de recepción negativa iniciada por el cliente, solo se puede usar el ID de confirmación más reciente para confirmar el mensaje. Cualquier solicitud con un ID de confirmación anterior falla.
Con la función de entrega “exactamente una vez” habilitada, los suscriptores pueden asegurarse de que los mensajes se procesen una vez siguiendo estas instrucciones:
Confirma los mensajes dentro del plazo de confirmación.
Mantén la información sobre el progreso del procesamiento de un mensaje hasta que se confirme correctamente.
Usa la información sobre el progreso del procesamiento de un mensaje para evitar el trabajo duplicado cuando falla una confirmación.
Solo el tipo de suscripción de extracción admite la entrega “exactamente una vez”, incluidos los suscriptores que usan la API de StreamingPull. Las suscripciones de envío y exportación no admiten la entrega “exactamente una vez”.
Pub/Sub admite la entrega “exactamente una vez” dentro de una región de la nube, según un ID de mensaje único definido por Pub/Sub.
Versiones recomendadas de la biblioteca cliente
- Para obtener el mejor rendimiento, usa la versión más reciente de la biblioteca cliente, Python v2.13.6 o versiones posteriores, Java v1.139.0 o versiones posteriores, PHP v1.39.0 o versiones posteriores, C# v3.2.0 o versiones posteriores, C++ v2.1.0, Go v1.25.1 o versiones posteriores, Node v3.2.0 o versiones posteriores y Ruby v2.12.1 o versiones posteriores.
Comparación entre la reentrega y la duplicación
Es importante comprender la diferencia entre las reentregas esperadas y las inesperadas.
Una reentrega puede ocurrir debido a la confirmación de recepción negativa de un mensaje iniciada por el cliente o cuando el cliente no extiende el plazo de confirmación del mensaje antes de que venza. Las reentregas se consideran válidas y el sistema funciona según lo previsto.
Para solucionar problemas de reentregas, consulta Cómo lidiar con duplicados.
Una duplicación ocurre cuando se vuelve a enviar un mensaje después de una confirmación de recepción correcta o antes de que venza el plazo de confirmación.
Un mensaje reentregado conserva el mismo ID de mensaje entre los intentos de reentrega.
Las suscripciones con la entrega “exactamente una vez” habilitada no reciben entregas duplicadas.
Compatibilidad con la entrega “exactamente una vez” en las bibliotecas cliente
Las bibliotecas cliente compatibles tienen una interfaz para la confirmación de recepción con respuesta (por ejemplo: Go). Puedes usar esta interfaz para verificar si la solicitud de confirmación de recepción se realizó correctamente. Si la solicitud de confirmación de recepción se realiza correctamente, se garantiza que los clientes no recibirán una reentrega. Si la solicitud de confirmación de recepción falla, los clientes pueden esperar una reentrega.
Los clientes también pueden usar las bibliotecas cliente compatibles sin la interfaz de confirmación de recepción. Sin embargo, en esos casos, las fallas de confirmación de recepción pueden provocar reentregas silenciosas de mensajes.
Las bibliotecas cliente compatibles tienen interfaces para establecer el tiempo mínimo de extensión de la concesión (por ejemplo: Go). Debes establecer el valor de la extensión mínima de la concesión en un número alto para evitar cualquier vencimiento de confirmación de recepción relacionado con la red. El valor máximo se establece en 600 segundos.
Si usas la biblioteca cliente de Java y, además, inicializas tu suscriptor con un canal gRPC personalizado mediante el
setChannelProvider()método, te recomendamos que también establezcasmaxInboundMetadataSizeen al menos 1 MB cuando compiles tuTransportChannelProvider. Para esta configuración, puedes usar elInstantiatingGrpcChannelProvider.Builder.setMaxInboundMetadataSize()o elManagedChannelBuilder.maxInboundMetadataSize()método.
Los valores predeterminados y el rango de las variables relacionadas con la entrega “exactamente una vez” y los nombres de las variables pueden diferir entre las bibliotecas cliente. Por ejemplo, en la biblioteca cliente de Java, las siguientes variables controlan la entrega “exactamente una vez”.
| Variable | Descripción | Valor |
|---|---|---|
setEnableExactlyOnceDelivery |
Habilita o inhabilita la entrega “exactamente una vez”. | true o false Default=false |
minDurationPerAckExtension |
Es el tiempo mínimo en segundos que se usa para extender el plazo de confirmación de recepción de modificación. | Range=0 to 600 Default=none |
maxDurationPerAckExtension |
Es el tiempo máximo en segundos que se usa para extender el plazo de confirmación de recepción de modificación. | Range=0 to 600 Default=none |
En el caso de la entrega “exactamente una vez”, la modifyAckDeadline o acknowledgment
solicitud a Pub/Sub falla cuando el ID de confirmación de recepción ya venció. En esos casos, el servicio considera que el ID de confirmación de recepción vencido no es válido, ya que es posible que una entrega más reciente ya esté en curso. Este es el diseño para la entrega “exactamente una vez”. Luego, verás que las solicitudes acknowledgment y ModifyAckDeadline muestran una respuesta INVALID_ARGUMENT. Cuando la entrega “exactamente una vez” está inhabilitada, estas solicitudes muestran OK en los casos de IDs de confirmación de recepción vencidos.
Para asegurarte de que las solicitudes acknowledgment y ModifyAckDeadline tengan IDs de confirmación de recepción válidos, considera establecer el valor de minDurationPerAckExtension en un número alto.
Consideraciones regionales
La garantía de entrega “exactamente una vez” solo se aplica cuando los suscriptores se conectan al servicio en la misma región. Si tu aplicación suscriptora se distribuye en varias regiones, puede provocar la entrega de mensajes duplicados, incluso cuando la entrega “exactamente una vez” está habilitada. Los publicadores pueden enviar mensajes a cualquier región, y la garantía de “exactamente una vez” se mantiene.
Cuando ejecutas tu aplicación en Cloud de Confiance, de forma predeterminada, se conecta al extremo de Pub/Sub en la misma región. Por lo tanto, ejecutar tu aplicación en una sola región dentro de Cloud de Confiance generalmente garantiza que interactúes con una sola región.
Cuando ejecutas tu aplicación suscriptora fuera de Cloud de Confiance o en varias regiones, puedes garantizar que te conectas a una sola región usando un extremo de ubicación cuando configuras tu cliente de Pub/Sub Todos los extremos de ubicación para Pub/Sub apuntan a regiones únicas. Para obtener más información sobre los extremos de ubicación, consulta Extremos de Pub/Sub. Para obtener una lista de todos los extremos de ubicación para Pub/Sub, consulta Lista de extremos de ubicación.
Crea suscripciones con entrega “exactamente una vez”
Puedes crear una suscripción con entrega “exactamente una vez” usando la Cloud de Confiance consola de , Google Cloud CLI, la biblioteca cliente o la API de Pub/Sub.
Suscripción de extracción
Console
Para crear una suscripción de extracción con entrega “exactamente una vez”, sigue estos pasos:
En la Cloud de Confiance consola de, ve a la página Suscripciones.
Haz clic en Crear suscripción.
Ingresa el ID de suscripción.
Elige o crea un tema desde el menú desplegable.
La suscripción recibe mensajes del tema.
En la sección Entrega “exactamente una vez”, selecciona Habilitar entrega “exactamente una vez”.
Haz clic en Crear.
gcloud
Para crear una suscripción de extracción con entrega “exactamente una vez”, usa el
gcloud pubsub subscriptions create
comando con la --enable-exactly-once-delivery marca:
gcloud pubsub subscriptions create SUBSCRIPTION_ID \ --topic=TOPIC_ID \ --enable-exactly-once-delivery
Reemplaza lo siguiente:
- SUBSCRIPTION_ID: Es el ID de la suscripción que se creará.
- TOPIC_ID: Es el ID del tema para adjuntar a la suscripción.
REST
Para crear una suscripción con entrega “exactamente una vez”, usa el
projects.subscriptions.create
método.
PUT https://pubsub.googleapis.com/v1/projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID Authorization: Bearer $(gcloud auth print-access-token)
Reemplaza lo siguiente:
- PROJECT_ID: Es el ID del proyecto para crear la suscripción.
- SUBSCRIPTION_ID: Es el ID de la suscripción que se creará.
Para crear una suscripción de extracción con entrega “exactamente una vez”, especifica lo siguiente en el cuerpo de la solicitud:
{ "topic": "projects/PROJECT_ID/topics/TOPIC_ID", "enableExactlyOnceDelivery": true, }
Reemplaza lo siguiente:
- PROJECT_ID: el ID del proyecto con el tema
- TOPIC_ID: Es el ID del tema para adjuntar a la suscripción.
C++
Antes de probar esta muestra, sigue las instrucciones de configuración de C++ 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 C++ .
C#
Antes de probar esta muestra, sigue las instrucciones de configuración de C# 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 C#.
Go
En el siguiente ejemplo, se usa la versión principal de la biblioteca cliente de Pub/Sub para Go (v2). Si aún usas la biblioteca v1, consulta la guía de migración a la v2. Para ver una lista de ejemplos de código de la v1, consulta los ejemplos de código obsoletos.
Antes de probar esta muestra, sigue las instrucciones de configuración de Go 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 Go.
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 .
Python
Antes de probar esta muestra, sigue las instrucciones de configuración de Python 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 Python de Pub/Sub .
Node.js
Antes de probar esta muestra, sigue las instrucciones de configuración de Node.js 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 Node.js.
Node.js
Antes de probar esta muestra, sigue las instrucciones de configuración de Node.js 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 Node.js.
Ruby
En el siguiente ejemplo, se usa la biblioteca cliente de Pub/Sub para Ruby v3. Si aún usas la biblioteca v2, consulta la guía de migración a la v3. Para ver una lista de ejemplos de código de la v2 de Ruby, consulta los ejemplos de código obsoletos.
Antes de probar esta muestra, sigue las instrucciones de configuración de Ruby 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 Ruby.
PHP
Antes de probar esta muestra, sigue las instrucciones de configuración de PHP 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 PHP .
Supervisa las suscripciones con entrega “exactamente una vez”
La
subscription/exactly_once_warning_count
métrica registra la cantidad de eventos que
pueden provocar posibles reentregas (válidas o duplicadas). Esta métrica cuenta las veces que Pub/Sub no puede procesar las solicitudes asociadas con los IDs de confirmación de recepción (solicitud ModifyAckDeadline o acknowledgment). Los motivos de la falla pueden ser del servidor o del cliente. Por ejemplo, si la capa de persistencia que se usa para mantener la información de entrega “exactamente una vez” no está disponible, sería un evento basado en el servidor. Si el cliente intenta confirmar la recepción de un mensaje con un ID de confirmación de recepción no válido, sería un evento basado en el cliente.
Comprende la métrica
subscription/exactly_once_warning_count captura eventos que pueden o no provocar reentregas reales y puede ser ruidosa según el comportamiento del cliente. Por ejemplo, las solicitudes acknowledgment o ModifyAckDeadline repetidas con IDs de confirmación de recepción no válidos aumentan la métrica de forma repetida.
Las siguientes métricas también son útiles para comprender el comportamiento del cliente:
subscription/expired_ack_deadlines_countLa métrica muestra la cantidad de vencimientos de IDs de confirmación de recepción. Los vencimientos de IDs de confirmación de recepción pueden provocar fallas en las solicitudesModifyAckDeadlineyacknowledgment.service.serviceruntime.googleapis.com/api/request_countla métrica se puede usar para capturar fallas de solicitudesModifyAckDeadlineoacknowledgmenten los casos en que las solicitudes llegan a Cloud de Confiance by S3NS pero no a Pub/Sub. Hay fallas que esta métrica no capturará, por ejemplo, cuando los clientes se desconectan de Cloud de Confiance by S3NS.
En la mayoría de los casos de eventos de falla que se pueden volver a intentar, las bibliotecas cliente compatibles vuelven a intentar la solicitud automáticamente.
Cuotas
Las suscripciones con entrega “exactamente una vez” están sujetas a requisitos de cuota adicionales. Estas cuotas se aplican a lo siguiente:
- Cantidad de mensajes consumidos de suscripciones con entrega “exactamente una vez” habilitada por región
- Cantidad de mensajes confirmados o cuyo plazo se extiende cuando se usan suscripciones con entrega “exactamente una vez” habilitada por región
Para obtener más información sobre estas cuotas, consulta la tabla en el tema Cuotas.
Entrega “exactamente una vez” y suscripciones ordenadas
Pub/Sub admite la entrega “exactamente una vez” con la entrega ordenada.
Cuando se usa el ordenamiento con la entrega “exactamente una vez”, Pub/Sub espera que las confirmaciones de recepción estén en orden. Si las confirmaciones de recepción están desordenadas, el servicio falla las solicitudes con errores temporales. Si el plazo de confirmación de recepción vence antes de una confirmación de recepción en orden para la entrega, el cliente recibirá una reentrega del mensaje. Debido a esto, cuando usas el ordenamiento con la entrega “exactamente una vez”, la capacidad de procesamiento del cliente se limita a un orden de miles de mensajes por segundo.
Entrega “exactamente una vez” y suscripciones de envío
Pub/Sub admite la entrega “exactamente una vez” solo con suscripciones de extracción.
Los clientes que consumen mensajes de las suscripciones de envío confirman los mensajes respondiendo a las solicitudes de envío con una respuesta correcta. Sin embargo, los clientes no saben si la suscripción de Pub/Sub recibió la respuesta y la procesó. Esto es diferente de las suscripciones de extracción, en las que los clientes inician las solicitudes de confirmación de recepción y la suscripción de Pub/Sub responde si la solicitud se procesó correctamente. Debido a esto, la semántica de entrega “exactamente una vez” no se alinea bien con las suscripciones de envío.
Información importante
Si no se especifica el plazo de confirmación de recepción en el momento de CreateSubscription, las suscripciones habilitadas para la entrega “exactamente una vez” tendrán un plazo de confirmación de recepción predeterminado de 60 segundos.
Los plazos de confirmación de recepción predeterminados más largos son beneficiosos para evitar la reentrega causada por eventos de red. Las bibliotecas cliente compatibles no usan el plazo de confirmación de recepción predeterminado de la suscripción.
Las suscripciones con entrega “exactamente una vez” tienen una latencia de publicación-suscripción significativamente mayor en comparación con las suscripciones normales.
Si necesitas una capacidad de procesamiento alta, tus clientes de entrega “exactamente una vez” también deben usar la extracción de transmisión.
Es posible que una suscripción reciba varias copias del mismo mensaje debido a duplicados del lado de la publicación, incluso con la entrega “exactamente una vez” habilitada. Los duplicados del lado de la publicación pueden deberse a varios reintentos de publicación únicos por parte del cliente de publicación o del servicio de Pub/Sub. Varias publicaciones únicas por parte del cliente de publicación, en los reintentos, provocan reentregas con IDs de mensaje diferentes. Varias publicaciones únicas por parte del servicio de Pub/Sub, para responder a una solicitud de publicación del cliente, provocan reentregas con los mismos IDs de mensaje.
Puedes volver a intentar las fallas en
subscription/exactly_once_warning_count, y las bibliotecas cliente compatibles las vuelven a intentar automáticamente. Sin embargo, no se pueden volver a intentar las fallas relacionadas con IDs de confirmación de recepción no válidos.