Diffusion de type "exactement une fois"

Cette page explique comment recevoir des messages et en accuser réception à l'aide de la fonctionnalité "exactement une fois" de Pub/Sub, qui vous permet de suivre et d'empêcher le traitement en double des messages. Lorsque cette fonctionnalité est activée, Pub/Sub fournit la sémantique suivante :

  • Les abonnés peuvent déterminer si les accusés de réception des messages ont réussi.

  • Aucune redistribution n'a lieu une fois que le message a été confirmé.

  • Aucune redistribution n'a lieu lorsqu'un message est en attente. Un message est considéré comme en attente jusqu'à l'expiration du délai de confirmation ou jusqu'à ce qu'il soit confirmé.

  • En cas de plusieurs distributions valides, en raison de l'expiration du délai de confirmation ou d'un accusé de réception négatif initié par le client, seul le dernier ID d'accusé de réception peut être utilisé pour confirmer le message. Toutes les requêtes avec un ID d'accusé de réception précédent échouent.

Lorsque la fonctionnalité "exactement une fois" est activée, les abonnés peuvent s'assurer que les messages sont traités une seule fois en suivant ces consignes :

  • Accusez réception des messages dans le délai de confirmation.

  • Conservez les informations sur l'avancement du traitement d'un message jusqu'à ce qu'il soit confirmé.

  • Utilisez les informations sur l'avancement du traitement d'un message pour éviter le travail en double en cas d'échec de l'accusé de réception.

Seul le type d'abonnement pull est compatible avec la distribution de type "exactement une fois", y compris les abonnés qui utilisent l' API StreamingPull. Les abonnements push et d'exportation ne sont pas compatibles avec la distribution de type "exactement une fois".

Pub/Sub est compatible avec la distribution de type "exactement une fois" dans une région cloud, en fonction d'un ID de message unique défini par Pub/Sub message ID.

Redistribution et doublons

Il est important de comprendre la différence entre les redistributions attendues et inattendues.

  • Une redistribution peut se produire en raison d'un accusé de réception négatif d'un message initié par le client ou lorsque le client ne prolonge pas le délai de confirmation du message avant son expiration. Les redistributions sont considérées comme valides et le système fonctionne comme prévu.

    Pour résoudre les problèmes de redistribution, consultez la section Gérer les doublons.

  • Un doublon se produit lorsqu'un message est renvoyé après un accusé de réception réussi ou avant l'expiration du délai de confirmation.

  • Un message redistribué conserve le même ID de message entre les tentatives de redistribution.

Les abonnements pour lesquels la distribution de type "exactement une fois" est activée ne reçoivent pas de doublons.

Compatibilité avec la distribution de type "exactement une fois" dans les bibliothèques clientes

  • Les bibliothèques clientes compatibles disposent d'une interface d'accusé de réception avec réponse (exemple : Go). Vous pouvez utiliser cette interface pour vérifier si la requête d'accusé de réception a réussi. Si la requête d'accusé de réception réussit, les clients ne recevront pas de redistribution. Si la requête d'accusé de réception échoue, les clients peuvent s'attendre à une redistribution.

  • Les clients peuvent également utiliser les bibliothèques clientes compatibles sans l'interface d'accusé de réception. Toutefois, dans ce cas, les échecs d'accusé de réception peuvent entraîner des redistributions silencieuses de messages.

  • Les bibliothèques clientes compatibles disposent d'interfaces permettant de définir la durée minimale d'extension du bail (exemple : Go). Vous devez définir une valeur élevée pour la durée minimale d'extension du bail afin d'éviter toute expiration d'accusé de réception liée au réseau. La valeur maximale est de 600 secondes.

  • Si vous utilisez la bibliothèque cliente Java et que vous initialisez votre abonné avec un canal gRPC personnalisé à l'aide de la setChannelProvider() méthode, nous vous recommandons également de définir maxInboundMetadataSize sur au moins 1 Mo lors de la création de votre TransportChannelProvider. Pour cette configuration, vous pouvez utiliser la InstantiatingGrpcChannelProvider.Builder.setMaxInboundMetadataSize() ou la ManagedChannelBuilder.maxInboundMetadataSize() méthode.

Les valeurs par défaut et la plage des variables liées à la distribution de type "exactement une fois", ainsi que les noms des variables, peuvent varier d'une bibliothèque cliente à l'autre. Par exemple, dans la bibliothèque cliente Java, les variables suivantes contrôlent la distribution de type "exactement une fois".

Variable Description Valeur
setEnableExactlyOnceDelivery Active ou désactive la distribution de type "exactement une fois". true ou false Valeur par défaut : false
minDurationPerAckExtension Durée minimale en secondes à utiliser pour prolonger le délai de confirmation de la modification. Plage : 0 à 600 Valeur par défaut : none
maxDurationPerAckExtension Durée maximale en secondes à utiliser pour prolonger le délai de confirmation de la modification. Plage : 0 à 600 Valeur par défaut : none

Dans le cas d'une distribution de type "exactement une fois", la modifyAckDeadline ou acknowledgment adressée à Pub/Sub échoue lorsque l'ID d'accusé de réception a déjà expiré. Dans ce cas, le service considère l'ID d'accusé de réception expiré comme non valide, car une distribution plus récente est peut-être déjà en cours. Ceci est intentionnel pour la distribution de type "exactement une fois". Les requêtes acknowledgment et ModifyAckDeadline renvoient alors une réponse INVALID_ARGUMENT. Lorsque la distribution de type "exactement une fois" est désactivée, ces requêtes renvoient OK en cas d'ID d'accusé de réception expiré.

Pour vous assurer que les requêtes acknowledgment et ModifyAckDeadline disposent d'ID d'accusé de réception valides, envisagez de définir une valeur élevée pour minDurationPerAckExtension.

Points à prendre en compte concernant les régions

La garantie de distribution de type "exactement une fois" ne s'applique que lorsque les abonnés se connectent au service dans la même région. Si votre application abonnée est répartie sur plusieurs régions, cela peut entraîner une distribution de messages en double, même lorsque la distribution de type "exactement une fois" est activée. Les éditeurs peuvent envoyer des messages à n'importe quelle région, et la garantie de distribution de type "exactement une fois" est toujours maintenue.

Lorsque vous exécutez votre application dans Google Cloud, elle se connecte par défaut au point de terminaison Pub/Sub dans la même région. Par conséquent, l'exécution de votre application dans une seule région au sein de Google Cloud garantit généralement que vous interagissez avec une seule région.

Lorsque vous exécutez votre application abonnée en dehors de Google Cloud ou dans plusieurs régions, vous pouvez vous assurer que vous vous connectez à une seule région en utilisant un point de terminaison géographique lors de la configuration de votre client Pub/Sub. Tous les points de terminaison géographiques pour Pub/Sub pointent vers des régions uniques. Pour en savoir plus sur les points de terminaison géographiques, consultez Points de terminaison Pub/Sub. Pour obtenir la liste de tous les points de terminaison géographiques pour Pub/Sub, consultez Liste des points de terminaison géographiques.

Créer des abonnements avec distribution de type "exactement une fois"

Vous pouvez créer un abonnement avec distribution de type "exactement une fois" à l'aide de la Google Cloud console, de Google Cloud CLI, d'une bibliothèque cliente ou de l'API Pub/Sub.

Abonnement pull

Console

Pour créer un abonnement pull avec distribution de type "exactement une fois", procédez comme suit :

  1. Dans la Google Cloud console, accédez à la page Abonnements.

    Accéder à Abonnements

  2. Cliquez sur Créer un abonnement.

  3. Saisissez l'ID de l'abonnement.

  4. Choisissez ou créez un sujet dans le menu déroulant.

    L'abonnement reçoit les messages du sujet.

  5. Dans la section Distribution de type "exactement une fois", sélectionnez Activer la distribution de type "exactement une fois".

  6. Cliquez sur Créer.

gcloud

Pour créer un abonnement pull avec distribution de type "exactement une fois", exécutez la gcloud pubsub subscriptions create commande avec l'option --enable-exactly-once-delivery :

gcloud pubsub subscriptions create SUBSCRIPTION_ID \
  --topic=TOPIC_ID \
  --enable-exactly-once-delivery

Remplacez les éléments suivants :

  • SUBSCRIPTION_ID : ID de l'abonnement à créer
  • TOPIC_ID : ID du sujet à associer à l'abonnement

REST

Pour créer un abonnement avec distribution de type "exactement une fois", utilisez la projects.subscriptions.create méthode.

PUT https://pubsub.googleapis.com/v1/projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID
Authorization: Bearer $(gcloud auth print-access-token)

Remplacez les éléments suivants :

  • PROJECT_ID : ID du projet dans lequel créer l'abonnement
  • SUBSCRIPTION_ID : ID de l'abonnement à créer

Pour créer un abonnement pull avec distribution de type "exactement une fois", spécifiez-le dans le corps de la requête :

{
  "topic": "projects/PROJECT_ID/topics/TOPIC_ID",
  "enableExactlyOnceDelivery": true,
}

Remplacez les éléments suivants :

  • PROJECT_ID : ID du projet contenant le sujet.
  • TOPIC_ID : ID du sujet à associer à l'abonnement

C++

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage C++ qui se trouvent sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API Pub/Sub pour C++ .

namespace pubsub = ::google::cloud::pubsub;
namespace pubsub_admin = ::google::cloud::pubsub_admin;
[](pubsub_admin::SubscriptionAdminClient client,
   std::string const& project_id, std::string const& topic_id,
   std::string const& subscription_id) {
  google::pubsub::v1::Subscription request;
  request.set_name(
      pubsub::Subscription(project_id, subscription_id).FullName());
  request.set_topic(pubsub::Topic(project_id, topic_id).FullName());
  request.set_enable_exactly_once_delivery(true);
  auto sub = client.CreateSubscription(request);
  if (sub.status().code() == google::cloud::StatusCode::kAlreadyExists) {
    std::cout << "The subscription already exists\n";
    return;
  }
  if (!sub) throw std::move(sub).status();

  std::cout << "The subscription was successfully created: "
            << sub->DebugString() << "\n";
}

C#

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage C# qui se trouvent sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence sur l'API Pub/Sub pour C#.


using Google.Cloud.PubSub.V1;
using Grpc.Core;

public class CreateSubscriptionWithExactlyOnceDeliverySample
{
    public Subscription CreateSubscriptionWithExactlyOnceDelivery(string projectId, string topicId, string subscriptionId)
    {
        SubscriberServiceApiClient subscriber = SubscriberServiceApiClient.Create();
        TopicName topicName = TopicName.FromProjectTopic(projectId, topicId);
        SubscriptionName subscriptionName = SubscriptionName.FromProjectSubscription(projectId, subscriptionId);

        var subscriptionRequest = new Subscription
        {
            SubscriptionName = subscriptionName,
            TopicAsTopicName = topicName,
            EnableExactlyOnceDelivery = true
        };

        Subscription subscription = null;

        try
        {
            subscription = subscriber.CreateSubscription(subscriptionRequest);
        }
        catch (RpcException e) when (e.Status.StatusCode == StatusCode.AlreadyExists)
        {
            // Already exists.  That's fine.
        }
        return subscription;
    }
}

Go

L'exemple suivant utilise la version majeure de la bibliothèque cliente Go Pub/Sub (v2). Si vous utilisez toujours la bibliothèque v1, consultez le guide de migration vers la v2. Pour afficher la liste des exemples de code v1, consultez les exemples de code obsolètes.

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage Go qui se trouvent sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API Pub/Sub pour Go.

import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/pubsub/v2"
	"cloud.google.com/go/pubsub/v2/apiv1/pubsubpb"
)

func createSubscriptionWithExactlyOnceDelivery(w io.Writer, projectID, topic, subscription string) error {
	// projectID := "my-project-id"
	// topic := "projects/my-project-id/topics/my-topic"
	// subscription := "projects/my-project/subscriptions/my-sub"
	ctx := context.Background()
	client, err := pubsub.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("pubsub.NewClient: %w", err)
	}
	defer client.Close()

	pbSub := &pubsubpb.Subscription{
		Name:                      subscription,
		Topic:                     topic,
		EnableExactlyOnceDelivery: true,
	}
	sub, err := client.SubscriptionAdminClient.CreateSubscription(ctx, pbSub)
	if err != nil {
		return fmt.Errorf("failed to create exactly once sub: %w", err)
	}
	fmt.Fprintf(w, "Created a subscription with exactly once delivery enabled: %v\n", sub)
	return nil
}

Java

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage Java se trouvant sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API Pub/Sub pour Java .

import com.google.cloud.pubsub.v1.SubscriptionAdminClient;
import com.google.pubsub.v1.ProjectSubscriptionName;
import com.google.pubsub.v1.ProjectTopicName;
import com.google.pubsub.v1.Subscription;
import java.io.IOException;

public class CreateSubscriptionWithExactlyOnceDelivery {
  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";
    String subscriptionId = "your-subscription-id";

    createSubscriptionWithExactlyOnceDeliveryExample(projectId, topicId, subscriptionId);
  }

  public static void createSubscriptionWithExactlyOnceDeliveryExample(
      String projectId, String topicId, String subscriptionId) throws IOException {
    try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {

      ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId);
      ProjectSubscriptionName subscriptionName =
          ProjectSubscriptionName.of(projectId, subscriptionId);

      Subscription subscription =
          subscriptionAdminClient.createSubscription(
              Subscription.newBuilder()
                  .setName(subscriptionName.toString())
                  .setTopic(topicName.toString())
                  // Enable exactly once delivery in the subscription.
                  .setEnableExactlyOnceDelivery(true)
                  .build());

      System.out.println(
          "Created a subscription with exactly once delivery enabled: "
              + subscription.getAllFields());
    }
  }
}

Python

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage Python qui se trouvent sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence sur l'API Pub/Sub pour Python.

from google.cloud import pubsub_v1

# TODO(developer): Choose an existing topic.
# project_id = "your-project-id"
# topic_id = "your-topic-id"
# subscription_id = "your-subscription-id"

publisher = pubsub_v1.PublisherClient()
subscriber = pubsub_v1.SubscriberClient()
topic_path = publisher.topic_path(project_id, topic_id)
subscription_path = subscriber.subscription_path(project_id, subscription_id)

with subscriber:
    subscription = subscriber.create_subscription(
        request={
            "name": subscription_path,
            "topic": topic_path,
            "enable_exactly_once_delivery": True,
        }
    )
    print(
        f"Created subscription with exactly once delivery enabled: {subscription}"
    )

Node.js

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage Node.js qui se trouvent sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API Pub/Sub pour Node.js.

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID';
// const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';

// Imports the Google Cloud client library
const {PubSub} = require('@google-cloud/pubsub');

// Creates a client; cache this for further use
const pubSubClient = new PubSub();

async function createSubscriptionWithExactlyOnceDelivery(
  topicNameOrId,
  subscriptionNameOrId,
) {
  // Creates a new subscription
  await pubSubClient
    .topic(topicNameOrId)
    .createSubscription(subscriptionNameOrId, {
      enableExactlyOnceDelivery: true,
    });
  console.log(
    `Created subscription ${subscriptionNameOrId} with exactly-once delivery.`,
  );
  console.log(
    'To process messages, remember to check the return value of ackWithResponse().',
  );
}

Node.js

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage Node.js qui se trouvent sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API Pub/Sub pour Node.js.

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID';
// const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';

// Imports the Google Cloud client library
import {PubSub} from '@google-cloud/pubsub';

// Creates a client; cache this for further use
const pubSubClient = new PubSub();

async function createSubscriptionWithExactlyOnceDelivery(
  topicNameOrId: string,
  subscriptionNameOrId: string,
) {
  // Creates a new subscription
  await pubSubClient
    .topic(topicNameOrId)
    .createSubscription(subscriptionNameOrId, {
      enableExactlyOnceDelivery: true,
    });
  console.log(
    `Created subscription ${subscriptionNameOrId} with exactly-once delivery.`,
  );
  console.log(
    'To process messages, remember to check the return value of ackWithResponse().',
  );
}

Ruby

L'exemple suivant utilise la bibliothèque cliente Ruby Pub/Sub v3. Si vous utilisez toujours la bibliothèque v2, consultez le guide de migration vers la v3. Pour afficher la liste des exemples de code Ruby v2, consultez les exemples de code obsolètes.

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage Ruby qui se trouvent sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API Pub/Sub pour Ruby.

# project_id = "your-project-id"
# topic_id = "your-topic-id"
# subscription_id = "your-subscription-id"

pubsub = Google::Cloud::PubSub.new project_id: project_id
subscription_admin = pubsub.subscription_admin

subscription = subscription_admin.create_subscription \
  name: pubsub.subscription_path(subscription_id),
  topic: pubsub.topic_path(topic_id),
  enable_exactly_once_delivery: true

puts "Created subscription with exactly once delivery enabled: " \
     "#{subscription_id}"

PHP

Avant d'essayer cet exemple, suivez les instructions d'installation dans le langage PHP qui se trouvent sur la page Démarrage rapide : utiliser des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API Pub/Sub pour PHP.

use Google\Cloud\PubSub\PubSubClient;

/**
 * Creates a Pub/Sub subscription with `Exactly Once Delivery` enabled.
 *
 * @param string $projectId  The Google project ID.
 * @param string $topicName  The Pub/Sub topic name.
 * @param string $subscriptionName  The Pub/Sub subscription name.
 */
function create_subscription_with_exactly_once_delivery(
    string $projectId,
    string $topicName,
    string $subscriptionName
): void {
    $pubsub = new PubSubClient([
        'projectId' => $projectId,
    ]);
    $topic = $pubsub->topic($topicName);
    $subscription = $topic->subscription($subscriptionName);
    $subscription->create([
        'enableExactlyOnceDelivery' => true
    ]);

    // Exactly Once Delivery status for the subscription
    $status = $subscription->info()['enableExactlyOnceDelivery'];

    printf('Subscription created with exactly once delivery status: %s' . PHP_EOL, $status ? 'true' : 'false');
}

Surveiller les abonnements avec distribution de type "exactement une fois"

La métrique subscription/exactly_once_warning_count enregistre le nombre d'événements susceptibles d'entraîner des redistributions (valides ou en double). Cette métrique comptabilise le nombre de fois où Pub/Sub ne parvient pas à traiter les requêtes associées aux ID d'accusé de réception (requête ModifyAckDeadline ou acknowledgment). Les raisons de l'échec peuvent être liées au serveur ou au client. Par exemple, si la couche de persistance utilisée pour conserver les informations de distribution de type "exactement une fois" n'est pas disponible, il s'agit d'un événement côté serveur. Si le client tente de confirmer un message avec un ID d'accusé de réception non valide, il s'agit d'un événement côté client.

Comprendre la métrique

subscription/exactly_once_warning_count capture les événements qui peuvent ou non entraîner des redistributions réelles et peut être bruyant en fonction du comportement du client. Par exemple, les requêtes acknowledgment ou ModifyAckDeadline répétées avec des ID d'accusé de réception non valides incrémentent la métrique de manière répétée.

Les métriques suivantes sont également utiles pour comprendre le comportement du client :

  • subscription/expired_ack_deadlines_count La métrique indique le nombre d'expirations d'ID d'accusé de réception. Les expirations d'ID d'accusé de réception peuvent entraîner des échecs pour les requêtes ModifyAckDeadline et acknowledgment.

  • service.serviceruntime.googleapis.com/api/request_count La métrique peut être utilisée pour capturer les échecs des requêtes ModifyAckDeadline ou acknowledgment dans les cas où les requêtes atteignent Google Cloud mais n'atteignent pas Pub/Sub. Cette métrique ne capture pas certains échecs, par exemple lorsque les clients sont déconnectés de Google Cloud.

Dans la plupart des cas d'événements d'échec pouvant être réessayés, les bibliothèques clientes compatibles réessaient automatiquement la requête.

Quotas

Les abonnements avec distribution de type "exactement une fois" sont soumis à des exigences de quota supplémentaires. Ces quotas sont appliqués aux éléments suivants :

  • Nombre de messages consommés à partir d'abonnements pour lesquels la distribution de type "exactement une fois" est activée par région.
  • Nombre de messages confirmés ou dont le délai est prolongé lors de l'utilisation d'abonnements pour lesquels la distribution de type "exactement une fois" est activée par région.

Pour en savoir plus sur ces quotas, consultez le tableau de la section Quotas.

Distribution de type "exactement une fois" et abonnements ordonnés

Pub/Sub est compatible avec la distribution de type "exactement une fois" avec la distribution ordonnée.

Lorsque vous utilisez l'ordonnancement avec la distribution de type "exactement une fois", Pub/Sub s'attend à ce que les accusés de réception soient dans l'ordre. Si les accusés de réception ne sont pas dans l'ordre, le service échoue les requêtes avec des erreurs temporaires. Si le délai de confirmation expire avant un accusé de réception dans l'ordre pour la distribution, le client recevra une redistribution du message. Pour cette raison, lorsque vous utilisez l'ordonnancement avec la distribution de type "exactement une fois", le débit du client est limité à un ordre de milliers de messages par seconde.

Distribution de type "exactement une fois" et abonnements push

Pub/Sub n'est compatible avec la distribution de type "exactement une fois" qu'avec les abonnements pull.

Les clients qui consomment des messages à partir des abonnements push accusent réception des messages en répondant aux requêtes push avec une réponse positive. Toutefois, les clients ne savent pas si l'abonnement Pub/Sub a reçu la réponse et l'a traitée. Cela diffère des abonnements pull, où les requêtes d'accusé de réception sont initiées par les clients et l'abonnement Pub/Sub répond si la requête a été traitée. Pour cette raison, la sémantique de distribution de type "exactement une fois" ne s'aligne pas bien sur les abonnements push.

Bon à savoir

  • Si le délai de confirmation n'est pas spécifié au moment de la création de l'abonnement, les abonnements pour lesquels la distribution de type "exactement une fois" est activée auront un délai de confirmation par défaut de 60 secondes.

  • Des délais de confirmation par défaut plus longs sont utiles pour éviter les redistributions causées par des événements réseau. Les bibliothèques clientes compatibles n'utilisent pas le délai de confirmation par défaut de l'abonnement.

  • Les abonnements avec distribution de type "exactement une fois" présentent une latence de publication vers l'abonnement nettement plus élevée que les abonnements standards.

  • Si vous avez besoin d'un haut débit, vos clients avec distribution de type "exactement une fois" doivent également utiliser le mode pull en streaming.

  • Un abonnement peut recevoir plusieurs copies du même message en raison de doublons côté publication, même si la distribution de type "exactement une fois" est activée. Les doublons côté publication peuvent être dus à plusieurs nouvelles tentatives de publication uniques par le client de publication ou le service Pub/Sub. Plusieurs publications uniques par le client de publication, lors de nouvelles tentatives, entraînent des redistributions avec différents ID de message. Plusieurs publications uniques par le service Pub/Sub, en réponse à une requête de publication du client, entraînent des redistributions avec les mêmes ID de message.

  • Vous pouvez réessayer les échecs dans subscription/exactly_once_warning_count, et les bibliothèques clientes compatibles les réessaient automatiquement. Toutefois, les échecs liés à des ID d'accusé de réception non valides ne peuvent pas être réessayés.