En esta página, se explica cómo recibir y confirmar mensajes con la función de Pub/Sub de “exactamente una vez”, que te permite hacer un seguimiento del procesamiento duplicado de mensajes y evitarlo. Cuando la función está habilitada, Pub/Sub proporciona la siguiente semántica:
Los suscriptores pueden determinar si las confirmaciones de mensajes se realizaron correctamente.
No se vuelve a enviar el mensaje después de que se confirma su recepción correctamente.
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 de recepción o se confirma la recepción del mensaje.
En caso de que haya 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 la recepción del mensaje. Las solicitudes con un ID de confirmación anterior fallarán.
Con la opción de procesamiento único habilitada, los suscriptores pueden garantizar que los mensajes se procesen una vez siguiendo estos lineamientos:
Confirma la recepción de los mensajes dentro del plazo de confirmación.
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 el trabajo duplicado cuando falla una confirmación.
Solo el tipo de suscripción de extracción admite la entrega del tipo “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 posterior, Java v1.139.0 o posterior, PHP v1.39.0 o posterior, C# v3.2.0 o posterior, C++ v2.1.0, Go v1.25.1 o posterior, Node v3.2.0 o posterior y Ruby v2.12.1 o posterior.
Redelivery versus duplicate
Es importante comprender la diferencia entre las reentregas esperadas y las inesperadas.
Un reenvío puede ocurrir debido a una confirmación de recepción negativa iniciada por el cliente de un mensaje o cuando el cliente no extiende el plazo de confirmación de recepción del mensaje antes de que venza. Las reentregas se consideran válidas y el sistema funciona según lo previsto.
Para solucionar problemas relacionados con los reenvíos, consulta Cómo controlar los duplicados.
Un duplicado se produce cuando se vuelve a enviar un mensaje después de una confirmación de recepción exitosa o antes de que venza el plazo de confirmación de recepción.
Un mensaje reentregado conserva el mismo ID 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 el acuse de recibo con respuesta (por ejemplo, Go). Puedes usar esta interfaz para verificar si la solicitud de confirmación se realizó correctamente. Si la solicitud de confirmación se realiza correctamente, se garantiza que los clientes no recibirán una nueva entrega. Si falla la solicitud de confirmación, los clientes pueden esperar una nueva entrega.
Los clientes también pueden usar las bibliotecas cliente compatibles sin la interfaz de confirmación. Sin embargo, en esos casos, las fallas en la confirmación pueden provocar reintentos silenciosos de entrega de mensajes.
Las bibliotecas cliente admitidas tienen interfaces para configurar el tiempo mínimo de extensión del alquiler (por ejemplo, Go). Debes establecer el valor de la extensión mínima del arrendamiento en un número alto para evitar que venzan los acuses de recibo relacionados con la red. El valor máximo se establece en 600 segundos.
Si usas la biblioteca cliente de Java y, luego, inicializas tu suscriptor con un canal de gRPC personalizado a través del método
setChannelProvider()
, te recomendamos que también establezcasmaxInboundMetadataSize
en, al menos, 1 MB cuando compiles tuTransportChannelProvider
. Para esta configuración, puedes usar el métodoInstantiatingGrpcChannelProvider.Builder.setMaxInboundMetadataSize()
o el métodoManagedChannelBuilder.maxInboundMetadataSize()
.
Los valores y el rango predeterminados para las variables relacionadas con la entrega exactamente una vez, así como 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”. | verdadero o falso. El valor predeterminado es falso. |
minDurationPerAckExtension |
Es el tiempo mínimo en segundos que se usará para extender el plazo de confirmación de modificación. | El rango es de 0 a 600. El valor predeterminado es ninguno. |
maxDurationPerAckExtension |
Es el tiempo máximo en segundos que se usará para extender el plazo de confirmación de modificación. | El rango es de 0 a 600. El valor predeterminado es 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 venció. En esos casos, el servicio considera que el ID de confirmación vencido no es válido, ya que es posible que ya esté en curso una entrega más reciente. Esto se debe al diseño de la entrega de exactamente una vez. Luego, 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 vencidos.
Para garantizar que las solicitudes acknowledgment
y ModifyAckDeadline
tengan IDs de confirmació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 de suscriptor se distribuye en varias regiones, se puede producir 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 entrega exactamente una vez se mantiene.
Cuando ejecutas tu aplicación dentro de Google Cloud, 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 Google Cloudgeneralmente garantiza que interactúes con una sola región.
Cuando ejecutas tu aplicación de suscriptor fuera de Google Cloudo 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 de 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 de Pub/Sub, consulta la lista de extremos de ubicación.
Crea suscripciones con entrega “exactamente una vez”
Puedes crear una suscripción con entrega exactamente una vez con la consola de Google Cloud , 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 consola de Google Cloud , 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 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
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 método projects.subscriptions.create
.
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
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 Pub/Sub para Python.
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
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.
Suscríbete con la entrega de mensajes “exactamente una vez”
A continuación, se incluyen algunas muestras de código para suscribirse con la entrega exactamente una vez usando la biblioteca cliente.
Suscripción de extracción
Go
Antes de probar esta muestra, sigue las instrucciones de configuración de Go en la guía de inicio rápido de Pub/Sub 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.
Para autenticarte en Pub/Sub, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.
Java
Antes de probar esta muestra, sigue las instrucciones de configuración de Java en la guía de inicio rápido de Pub/Sub 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.
Para autenticarte en Pub/Sub, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.
Node.js
Antes de probar esta muestra, sigue las instrucciones de configuración de Node.js en la guía de inicio rápido de Pub/Sub 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.
Para autenticarte en Pub/Sub, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.
PHP
Antes de probar esta muestra, sigue las instrucciones de configuración de PHP en la guía de inicio rápido de Pub/Sub 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.
Para autenticarte en Pub/Sub, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.
Python
Antes de probar esta muestra, sigue las instrucciones de configuración de Python en la guía de inicio rápido de Pub/Sub 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 Python.
Para autenticarte en Pub/Sub, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.
Ruby
Antes de probar esta muestra, sigue las instrucciones de configuración de Ruby en la guía de inicio rápido de Pub/Sub 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.
Para autenticarte en Pub/Sub, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.
C++
Antes de probar esta muestra, sigue las instrucciones de configuración de C++ en la guía de inicio rápido de Pub/Sub 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++.
Para autenticarte en Pub/Sub, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.
C#
Antes de probar esta muestra, sigue las instrucciones de configuración de C# en la guía de inicio rápido de Pub/Sub 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#.
Para autenticarte en Pub/Sub, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.
Node.js (TypeScript)
Antes de probar esta muestra, sigue las instrucciones de configuración de Node.js en la guía de inicio rápido de Pub/Sub con bibliotecas cliente. Si quieres obtener más información, consulta la documentación de referencia de la API de Pub/Sub para Node.js.
Para autenticarte en Pub/Sub, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.
Supervisa las suscripciones de entrega “exactamente una vez”
La métrica subscription/exactly_once_warning_count
registra la cantidad de eventos que pueden generar reintentos de entrega (válidos o duplicados). Esta métrica cuenta las veces que Pub/Sub no puede procesar las solicitudes asociadas con IDs de confirmació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, se trataría de un evento basado en el servidor. Si el cliente intenta confirmar la recepción de un mensaje con un ID de confirmación no válido, se tratará de un evento basado en el cliente.
Comprende la métrica
subscription/exactly_once_warning_count
captura eventos que pueden o no generar reenvíos reales y puede ser ruidoso según el comportamiento del cliente. Por ejemplo, las solicitudes acknowledgment
o ModifyAckDeadline
repetidas con IDs de confirmación no válidos incrementan la métrica de forma reiterada.
Las siguientes métricas también son útiles para comprender el comportamiento del cliente:
La métrica
subscription/expired_ack_deadlines_count
muestra la cantidad de vencimientos de IDs de confirmación. El vencimiento de los IDs de confirmación puede provocar fallas en las solicitudes deModifyAckDeadline
yacknowledgment
.La métrica
service.serviceruntime.googleapis.com/api/request_count
se puede usar para registrar las fallas de las solicitudes deModifyAckDeadline
oacknowledgment
en los casos en que las solicitudes llegan a Google Cloud , pero no a Pub/Sub. Hay fallas que esta métrica no capturará, por ejemplo, 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 cliente admitidas reintentan 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 la entrega exactamente una vez habilitada por región.
- Cantidad de mensajes confirmados o cuyo plazo se extendió cuando se usan suscripciones con la entrega única exacta habilitada por región.
Para obtener más información sobre estas cuotas, consulta la tabla en el tema Cuotas.
Suscripciones ordenadas y entrega “exactamente una vez”
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 los acuses de recibo estén en orden. Si los acuses de recibo están fuera de orden, el servicio rechaza las solicitudes con errores temporales. Si vence el plazo de confirmación antes de que se confirme la entrega en orden, el cliente recibirá una nueva entrega del mensaje. Por este motivo, cuando usas el ordenamiento con la entrega exactamente una vez, la capacidad de procesamiento del cliente se limita a un orden de mil mensajes por segundo.
Suscripciones push y entrega “exactamente una vez”
Pub/Sub admite la entrega exactamente una vez solo 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 exitosa. Sin embargo, los clientes no saben si la suscripción a Pub/Sub recibió la respuesta y la procesó. Esto es diferente de las suscripciones de extracción, en las que los clientes inician solicitudes de confirmación y la suscripción a Pub/Sub responde si la solicitud se procesó correctamente. Por este motivo, la semántica de entrega “exactamente una vez” no se alinea bien con las suscripciones de envío.
Qué debes saber
Si no se especifica el plazo de confirmación en el momento de CreateSubscription, las suscripciones con la entrega 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 beneficiosos para evitar la reentrega causada por eventos de red. Las bibliotecas cliente compatibles no usan el plazo predeterminado de confirmación de 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. Las múltiples publicaciones únicas del cliente de publicación, en todos los reintentos, generan reenvíos con diferentes IDs de mensaje. Las múltiples publicaciones únicas del servicio de Pub/Sub, en respuesta a una solicitud de publicación del cliente, generan reenvíos con los mismos IDs de mensaje.
Puedes volver a intentar las fallas en
subscription/exactly_once_warning_count
, y las bibliotecas cliente compatibles lo reintentarán automáticamente. Sin embargo, no se pueden volver a intentar los errores relacionados con IDs de confirmación no válidos.