En esta página se explica cómo recibir y confirmar mensajes mediante la función de procesamiento una vez solo de Pub/Sub, que te permite hacer un seguimiento de los mensajes y evitar que se procesen dos veces. Cuando la función está habilitada, Pub/Sub proporciona la siguiente semántica:
Los suscriptores pueden determinar si las confirmaciones de mensajes se han realizado correctamente.
No se vuelve a enviar el mensaje después de que se haya confirmado correctamente.
No se vuelve a enviar un mensaje mientras esté pendiente. Un mensaje se considera pendiente hasta que vence el plazo de confirmación o hasta que se confirma.
En caso de que haya varias entregas válidas debido a que haya vencido el plazo de confirmación o a que el cliente haya enviado una confirmación negativa, solo se puede usar el ID de confirmación más reciente para confirmar el mensaje. Se producirá un error en cualquier solicitud con un ID de confirmación anterior.
Si se habilita el procesamiento exacto, los suscriptores pueden asegurarse de que los mensajes se procesen una vez siguiendo estas directrices:
Confirmar los mensajes antes de la fecha límite.
Mantener 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 que se duplique el trabajo cuando falla una confirmación.
Solo el tipo de suscripción de extracción admite el envío exactamente una vez, incluidos los suscriptores que usan la API StreamingPull. Las suscripciones push y de exportación no admiten la entrega exactamente una vez.
Pub/Sub admite la entrega exactamente una vez en una región de la nube, basada en un ID de mensaje único definido por Pub/Sub.
Versiones recomendadas de la biblioteca de cliente
- Para obtener el mejor rendimiento, usa la versión más reciente de la biblioteca de cliente: Python 2.13.6 o una versión posterior, Java 1.139.0 o una versión posterior, PHP 1.39.0 o una versión posterior, C# 3.2.0 o una versión posterior, C++ v2.1.0, Go 1.25.1 o una versión posterior, Node 3.2.0 o una versión posterior y Ruby 2.12.1 o una versión posterior.
Volver a proporcionar frente a duplicar
Es importante entender la diferencia entre las reintentos de envío esperados e inesperados.
Una nueva entrega puede producirse debido a una confirmación negativa iniciada por el cliente de un mensaje o cuando el cliente no amplía el plazo de confirmación del mensaje antes de que expire. Las reentregas se consideran válidas y el sistema funciona según lo previsto.
Para solucionar problemas de reenvío, consulta Gestionar duplicados.
Se produce una duplicación cuando se vuelve a enviar un mensaje después de que se haya confirmado correctamente o antes de que caduque el plazo de confirmación.
Un mensaje reenviado conserva el mismo ID de mensaje entre los intentos de reenvío.
Las suscripciones con la entrega exactamente una vez habilitada no reciben entregas duplicadas.
Compatibilidad con la entrega exactamente una vez en bibliotecas de cliente
Las bibliotecas de cliente admitidas tienen una interfaz para la confirmación con respuesta (por ejemplo, Go). Puedes usar esta interfaz para comprobar si la solicitud de confirmación se ha realizado correctamente. Si la solicitud de confirmación se realiza correctamente, los clientes tienen la garantía de no recibir una nueva entrega. Si la solicitud de confirmación falla, los clientes pueden esperar una nueva entrega.
Los clientes también pueden usar las bibliotecas de cliente admitidas sin la interfaz de confirmación. Sin embargo, en estos casos, los errores de confirmación pueden provocar que los mensajes se vuelvan a enviar de forma silenciosa.
Las bibliotecas de cliente admitidas tienen interfaces para definir el tiempo mínimo de extensión de la concesión (por ejemplo, Go). Debe asignar un valor alto a la extensión mínima de la concesión para evitar que caduquen las confirmaciones relacionadas con la red. El valor máximo es de 600 segundos.
Si usas la biblioteca de cliente de Java e inicializas tu suscriptor con un canal gRPC personalizado mediante el método
setChannelProvider()
, te recomendamos que también definasmaxInboundMetadataSize
en al menos 1 MB al crear tuTransportChannelProvider
. Para esta configuración, puedes usar el métodoInstantiatingGrpcChannelProvider.Builder.setMaxInboundMetadataSize()
o el métodoManagedChannelBuilder.maxInboundMetadataSize()
.
Los valores predeterminados y el intervalo de las variables relacionadas con el envío exactamente una vez y los nombres de las variables pueden variar en las bibliotecas de cliente. Por ejemplo, en la biblioteca de cliente de Java, las siguientes variables controlan el envío exactamente una vez.
Variable | Descripción | Valor |
---|---|---|
setEnableExactlyOnceDelivery |
Habilita o inhabilita el envío exactamente una vez. | verdadero o falso. Valor predeterminado: falso. |
minDurationPerAckExtension |
Tiempo mínimo en segundos que se debe usar para ampliar el plazo de confirmación de modificación. | Intervalo: de 0 a 600. Valor predeterminado: ninguno. |
maxDurationPerAckExtension |
Tiempo máximo en segundos que se puede usar para ampliar el plazo de confirmación de la modificación. | Intervalo: de 0 a 600. Valor predeterminado: ninguno. |
En el caso de la entrega exactamente una vez, la solicitud modifyAckDeadline
o acknowledgment
a Pub/Sub falla cuando el ID de confirmación ya ha caducado. En estos casos, el servicio considera que el ID de confirmación caducado no es válido, ya que es posible que ya se haya enviado una entrega más reciente. Este es el comportamiento programado para la entrega exactamente una vez. A continuación, verás que las solicitudes acknowledgment
y ModifyAckDeadline
devuelven una respuesta INVALID_ARGUMENT
. Cuando la entrega exactamente una vez está inhabilitada, estas solicitudes devuelven OK
en los casos de IDs de confirmación caducados.
Para asegurarse de que las solicitudes acknowledgment
y ModifyAckDeadline
tengan IDs de confirmación válidos, puede asignar un valor alto a minDurationPerAckExtension
.
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 de suscriptor se distribuye en varias regiones, puede provocar que los mensajes se entreguen por duplicado, incluso cuando la entrega exactamente una vez esté habilitada. Los editores pueden enviar mensajes a cualquier región y se sigue manteniendo la garantía de entrega exactamente una vez.
Cuando ejecutas tu aplicación en Google Cloud, se conecta de forma predeterminada al endpoint de Pub/Sub de la misma región. Por lo tanto, si ejecutas tu aplicación en una sola región de Google Cloud generalmente te aseguras de interactuar con una sola región.
Si ejecutas tu aplicación de suscriptor fuera de Google Cloud o en varias regiones, puedes asegurarte de que te conectas a una sola región usando un endpoint de ubicación al configurar tu cliente de Pub/Sub. Todos los endpoints de ubicación de Pub/Sub apuntan a regiones únicas. Para obtener más información sobre los endpoints de ubicación, consulta Endpoints de Pub/Sub. Para ver una lista de todos los endpoints de ubicación de Pub/Sub, consulta la lista de endpoints de ubicación.
Crear suscripciones con entrega exactamente una vez
Puedes crear una suscripción con entrega exactamente una vez mediante la consola de Google Cloud, la CLI de Google Cloud, la biblioteca de cliente o la API de Pub/Sub. Google Cloud
Suscripción de extracción
Consola
Para crear una suscripción de extracción con entrega exactamente una vez, sigue estos pasos:
En la Google Cloud consola, ve a la página Suscripciones.
Haz clic en Crear suscripción.
Introduce el ID de suscripción.
Elige o crea un tema en el menú desplegable.
La suscripción recibe mensajes del tema.
En la sección Entrega exactamente una vez, seleccione Habilitar entrega exactamente una vez.
Haz clic en Crear.
gcloud
Para crear una suscripción pull con entrega exactamente una vez, usa el comando gcloud pubsub subscriptions create
con la marca --enable-exactly-once-delivery
:
gcloud pubsub subscriptions create SUBSCRIPTION_ID \ --topic=TOPIC_ID \ --enable-exactly-once-delivery
Haz los cambios siguientes:
- SUBSCRIPTION_ID: ID de la suscripción que se va a crear.
- TOPIC_ID: el ID del tema al que se adjuntará la suscripción
REST
Para crear una suscripción con entrega exactamente una vez, usa el método projects.subscriptions.create
.
PUT https://pubsub.googleapis.com/v1/projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID Authorization: Bearer $(gcloud auth print-access-token)
Haz los cambios siguientes:
- PROJECT_ID: el ID del proyecto en el que se va a crear la suscripción
- SUBSCRIPTION_ID: ID de la suscripción que se va a 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, }
Haz los cambios siguientes:
- PROJECT_ID: el ID del proyecto que contiene el tema
- TOPIC_ID: el ID del tema al que se adjuntará la suscripción
C++
Antes de probar este ejemplo, sigue las instrucciones de configuración de C++ que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de C++ de Pub/Sub.
C#
Antes de probar este ejemplo, sigue las instrucciones de configuración de C# que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de C# de Pub/Sub.
Go
En el siguiente ejemplo se usa la versión principal de la biblioteca de cliente de Pub/Sub de Go (v2). Si sigues usando la biblioteca v1, consulta la guía de migración a la versión 2. Para ver una lista de ejemplos de código de la versión 1, consulta los ejemplos de código obsoletos.
Antes de probar este ejemplo, sigue las instrucciones de configuración de Go que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API Go de Pub/Sub.
Java
Antes de probar este ejemplo, sigue las instrucciones de configuración de Java que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de Java de Pub/Sub.
Python
Antes de probar este ejemplo, sigue las instrucciones de configuración de Python que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de Python de Pub/Sub.
Node.js
Antes de probar este ejemplo, sigue las instrucciones de configuración de Node.js que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de Node.js de Pub/Sub.
Node.js
Antes de probar este ejemplo, sigue las instrucciones de configuración de Node.js que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de Node.js de Pub/Sub.
Ruby
En el siguiente ejemplo se usa la biblioteca de cliente de Ruby Pub/Sub v3. Si sigues usando la biblioteca v2, consulta la guía de migración a la versión 3. Para ver una lista de ejemplos de código de Ruby v2, consulta los ejemplos de código obsoletos.
Antes de probar este ejemplo, sigue las instrucciones de configuración de Ruby que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de Ruby de Pub/Sub.
PHP
Antes de probar este ejemplo, sigue las instrucciones de configuración de PHP que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de Pub/Sub para PHP.
Monitorizar suscripciones de entrega de mensajes exactamente una vez
La métrica
subscription/exactly_once_warning_count
registra el número de eventos que pueden provocar reenvíos (válidos o duplicados). Esta métrica cuenta las veces que Pub/Sub no puede procesar las solicitudes asociadas a IDs de confirmación (solicitud ModifyAckDeadline
o acknowledgment
). Los motivos
del fallo pueden deberse al servidor o al cliente. Por ejemplo, si la capa de persistencia utilizada para mantener la información de entrega exactamente una vez no está disponible, se trataría de un evento basado en el servidor. Si el cliente intenta confirmar un mensaje con un ID de confirmación no válido, se trataría de un evento basado en el cliente.
Familiarizarse con la métrica
subscription/exactly_once_warning_count
registra eventos que pueden o no provocar reenvíos reales y puede ser ruidoso en función del comportamiento del cliente. Por ejemplo, las solicitudes repetidas de acknowledgment
o ModifyAckDeadline
con IDs de confirmación no válidos incrementan la métrica repetidamente.
Las siguientes métricas también son útiles para comprender el comportamiento de los clientes:
subscription/expired_ack_deadlines_count
muestra el número de expiraciones de IDs de confirmación. Si caducan los IDs de confirmación, se pueden producir errores en las solicitudesModifyAckDeadline
yacknowledgment
.La métrica
service.serviceruntime.googleapis.com/api/request_count
se puede usar para registrar los errores de las solicitudesModifyAckDeadline
oacknowledgment
en los casos en los que las solicitudes llegan a Google Cloud , pero no a Pub/Sub. Hay fallos que esta métrica no registrará, como cuando los clientes se desconectan de Google Cloud.
En la mayoría de los casos de eventos de error que se pueden reintentar, las bibliotecas de cliente admitidas reintentan la solicitud automáticamente.
Cuotas
Las suscripciones de entrega exactamente una vez están sujetas a requisitos de cuota adicionales. Estas cuotas se aplican en los siguientes casos:
- Número de mensajes consumidos de suscripciones con la opción de entrega exactamente una vez habilitada por región.
- Número de mensajes confirmados o cuyo plazo se ha ampliado al usar suscripciones con la opción de envío exactamente una vez habilitada por región.
Para obtener más información sobre estas cuotas, consulta la tabla del tema Cuotas.
Entrega única y suscripciones ordenadas
Pub/Sub admite la entrega exacta una sola vez con la entrega ordenada.
Cuando se usa la ordenación con la entrega exactamente una vez, Pub/Sub espera que las confirmaciones estén ordenadas. Si los acuses de recibo no están en orden, el servicio rechaza las solicitudes con errores temporales. Si el plazo de confirmación vence antes de que se confirme la entrega, el cliente recibirá una nueva entrega del mensaje. Por este motivo, cuando usas la ordenación con la entrega exactamente una vez, el rendimiento del cliente se limita a un orden de mil mensajes por segundo.
Entrega exacta y suscripciones push
Pub/Sub solo admite la entrega de mensajes una sola vez con suscripciones de extracción.
Los clientes que consumen mensajes de las suscripciones push confirman la recepción de los mensajes respondiendo a las solicitudes push con una respuesta correcta. Sin embargo, los clientes no saben si la suscripción de Pub/Sub ha recibido la respuesta y la ha procesado. Esto es diferente de las suscripciones de extracción, en las que los clientes inician las solicitudes de confirmación y la suscripción de Pub/Sub responde si la solicitud se ha procesado correctamente. Por este motivo, la semántica de envío exactamente una vez no se ajusta bien a las suscripciones push.
Puntos a tener en cuenta
Si no se especifica ningún plazo de confirmación al crear la suscripción, las suscripciones con la opción de envío exactamente una vez habilitada tendrán un plazo de confirmación predeterminado de 60 segundos.
Los plazos de confirmación predeterminados más largos son útiles para evitar que se vuelva a enviar el contenido debido a eventos de red. Las bibliotecas de cliente admitidas no usan el plazo de confirmación de suscripción predeterminado.
Las suscripciones con entrega exactamente una vez tienen una latencia de publicación a suscripción significativamente mayor que las suscripciones normales.
Si necesitas un alto rendimiento, tus clientes de entrega exactamente una vez también deben usar streaming pull.
Una suscripción puede recibir varias copias del mismo mensaje debido a duplicados del lado de la publicación, incluso si se ha habilitado la entrega exactamente una vez. Las duplicaciones 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 Pub/Sub. Si el cliente de publicación publica varios elementos únicos en diferentes reintentos, se producirán reenvíos con diferentes IDs de mensaje. Si el servicio Pub/Sub publica varios mensajes únicos para responder a una solicitud de publicación de un cliente, se volverán a enviar con los mismos IDs de mensaje.
Puedes volver a intentar las operaciones fallidas en
subscription/exactly_once_warning_count
y las bibliotecas de cliente admitidas lo harán automáticamente. Sin embargo, los errores relacionados con IDs de confirmación no válidos no se pueden reintentar.