Consegna "exactly-once"

Questa pagina spiega come ricevere e confermare i messaggi utilizzando la funzionalità exactly-once di Pub/Sub, che consente di monitorare e impedire l'elaborazione duplicata dei messaggi. Quando la funzionalità è attivata, Pub/Sub fornisce la seguente semantica:

  • Gli abbonati possono determinare se gli ACK dei messaggi sono andati a buon fine.

  • Non viene eseguita alcuna nuova consegna dopo la conferma della ricezione del messaggio.

  • Non viene eseguita alcuna nuova consegna mentre un messaggio è in sospeso. Un messaggio viene considerato in sospeso fino alla scadenza del termine di conferma o fino a quando non viene confermato.

  • In caso di più consegne valide, a causa della scadenza del termine di conferma o della conferma negativa avviata dal client, è possibile utilizzare solo l'ultimo ID conferma per confermare il messaggio. Tutte le richieste con un ID di conferma precedente non vanno a buon fine.

Con l'elaborazione exactly-once attivata, i sottoscrittori possono assicurarsi che i messaggi vengano elaborati una sola volta seguendo queste linee guida:

  • Conferma i messaggi entro la scadenza di conferma.

  • Mantieni le informazioni sullo stato di avanzamento dell'elaborazione di un messaggio finché non viene confermato correttamente.

  • Utilizza le informazioni sullo stato di avanzamento dell'elaborazione di un messaggio per evitare duplicazioni del lavoro quando un riconoscimento non va a buon fine.

Solo il tipo di sottoscrizione pull supporta la distribuzione esattamente una volta, inclusi gli abbonati che utilizzano l'API StreamingPull. Le sottoscrizioni push e di esportazione non supportano la consegna "exactly-once".

Pub/Sub supporta la consegna exactly-once, all'interno di una regione cloud, in base a un ID messaggio univoco definito da Pub/Sub.

Ricaricamento e duplicato

È importante comprendere la differenza tra le riproposte previste e quelle impreviste.

  • Una nuova consegna può avvenire a causa di un riconoscimento negativo avviato dal client di un messaggio o quando il client non estende la scadenza del riconoscimento del messaggio prima che scada. Le nuove consegne sono considerate valide e il sistema funziona come previsto.

    Per risolvere i problemi relativi alle nuove consegne, consulta la sezione Gestire i duplicati.

  • Un duplicato si verifica quando un messaggio viene inviato nuovamente dopo una conferma di ricezione riuscita o prima della scadenza della conferma di ricezione.

  • Un messaggio riconsegnato mantiene lo stesso ID messaggio tra i tentativi di riconsegna.

Le sottoscrizioni con la consegna "exactly-once" abilitata non ricevono consegne duplicate.

Supporto della consegna "exactly-once" nelle librerie client

  • Le librerie client supportate hanno un'interfaccia per l'acknowledgement con risposta (ad esempio, Go). Puoi utilizzare questa interfaccia per verificare se la richiesta di riconoscimento è andata a buon fine. Se la richiesta di riconoscimento va a buon fine, i client hanno la garanzia di non ricevere una nuova consegna. Se la richiesta di riconoscimento non va a buon fine, i clienti possono aspettarsi una nuova consegna.

  • I client possono anche utilizzare le librerie client supportate senza l'interfaccia di riconoscimento. Tuttavia, in questi casi, gli errori di riconoscimento possono comportare la nuova consegna silenziosa dei messaggi.

  • Le librerie client supportate hanno interfacce per impostare il tempo minimo di estensione del lease (esempio: Go). Devi impostare il valore dell'estensione minima del lease su un numero elevato per evitare la scadenza degli ACK correlati alla rete. Il valore massimo è impostato su 600 secondi.

  • Se utilizzi la libreria client Java e inizializzi l'abbonato con un canale gRPC personalizzato utilizzando il metodo setChannelProvider(), ti consigliamo di impostare maxInboundMetadataSize su almeno 1 MB durante la creazione di TransportChannelProvider. Per questa configurazione, puoi utilizzare il metodo InstantiatingGrpcChannelProvider.Builder.setMaxInboundMetadataSize() o il metodo ManagedChannelBuilder.maxInboundMetadataSize().

I valori e l'intervallo predefiniti per le variabili relative alla distribuzione esatta e i nomi delle variabili potrebbero variare a seconda delle librerie client. Ad esempio, nella libreria client Java, le seguenti variabili controllano la distribuzione esattamente una volta.

Variabile Descrizione Valore
setEnableExactlyOnceDelivery Attiva o disattiva la consegna "exactly-once". true o false Default=false
minDurationPerAckExtension Il tempo minimo in secondi da utilizzare per estendere la scadenza dell'acknowledgement di modifica. Intervallo=da 0 a 600. Valore predefinito=nessuno.
maxDurationPerAckExtension Il tempo massimo in secondi da utilizzare per estendere la scadenza della conferma della modifica. Intervallo=da 0 a 600. Valore predefinito=nessuno.

Nel caso di invio esattamente una volta, la richiesta modifyAckDeadline o acknowledgment a Pub/Sub non va a buon fine quando l'ID riconoscimento è già scaduto. In questi casi, il servizio considera l'ID riconoscimento scaduto non valido, poiché potrebbe essere già in corso una consegna più recente. Questo è il comportamento predefinito per la consegna esattamente una volta. Vedrai quindi che le richieste acknowledgment e ModifyAckDeadline restituiscono una risposta INVALID_ARGUMENT. Quando la consegna esatta è disattivata, queste richieste restituiscono OK in caso di ID riconoscimento scaduti.

Per assicurarti che le richieste acknowledgment e ModifyAckDeadline abbiano ID riconoscimento validi, valuta la possibilità di impostare il valore di minDurationPerAckExtension su un numero elevato.

Considerazioni regionali

La garanzia di consegna "exactly-once" si applica solo quando gli abbonati si connettono al servizio nella stessa regione. Se l'applicazione di sottoscrizione è distribuita su più regioni, può comportare la consegna duplicata dei messaggi, anche quando è abilitata la consegna exactly-once. Gli editori possono inviare messaggi a qualsiasi regione e la garanzia di consegna "exactly-once" viene comunque mantenuta.

Quando esegui l'applicazione in Google Cloud, per impostazione predefinita si connette all'endpoint Pub/Sub nella stessa regione. Pertanto, l'esecuzione dell'applicazione in una singola regione all'interno di Google Cloud in genere garantisce l'interazione con una singola regione.

Quando esegui l'applicazione di sottoscrizione al di fuori di Google Cloud o in più regioni, puoi garantire la connessione a una singola regione utilizzando un endpoint di localizzazione durante la configurazione del client Pub/Sub. Tutti gli endpoint di località per Pub/Sub puntano a singole regioni. Per saperne di più sugli endpoint basati sulla località, consulta Endpoint Pub/Sub. Per un elenco di tutti gli endpoint basati sulla località per Pub/Sub, consulta Elenco degli endpoint basati sulla località.

Crea sottoscrizioni con la consegna "exactly-once"

Puoi creare una sottoscrizione con la funzionalità di distribuzione esatta una sola volta utilizzando la console Google Cloud , Google Cloud CLI, la libreria client o l'API Pub/Sub.

Sottoscrizione pull

Console

Per creare una sottoscrizione pull con la consegna esatta, segui questi passaggi:

  1. Nella console Google Cloud , vai alla pagina Sottoscrizioni.

    Vai agli abbonamenti

  2. Fai clic su Crea sottoscrizione.

  3. Inserisci l'ID abbonamento.

  4. Scegli o crea un argomento dal menu a discesa.

    La sottoscrizione riceve i messaggi dall'argomento.

  5. Nella sezione Consegna "exactly-once", seleziona Abilita la consegna "exactly-once".

  6. Fai clic su Crea.

gcloud

Per creare una sottoscrizione pull con la consegna esatta, utilizza il comando gcloud pubsub subscriptions create con il flag --enable-exactly-once-delivery:

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

Sostituisci quanto segue:

  • SUBSCRIPTION_ID: l'ID dell'abbonamento da creare
  • TOPIC_ID: l'ID dell'argomento da collegare all'abbonamento

REST

Per creare una sottoscrizione con la consegna exactly-once, utilizza il metodo projects.subscriptions.create.

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

Sostituisci quanto segue:

  • PROJECT_ID: l'ID progetto in cui creare l'abbonamento
  • SUBSCRIPTION_ID: l'ID dell'abbonamento da creare

Per creare una sottoscrizione pull con la consegna exactly-once, specifica quanto segue nel corpo della richiesta:

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

Sostituisci quanto segue:

  • PROJECT_ID: l'ID progetto del progetto con l'argomento
  • TOPIC_ID: l'ID dell'argomento da collegare all'abbonamento

C++

Prima di provare questo esempio, segui le istruzioni di configurazione di C++ nella guida rapida all'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API Pub/Sub 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#

Prima di provare questo esempio, segui le istruzioni di configurazione di C# nella guida rapida all'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API Pub/Sub 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;
    }
}

Vai

L'esempio seguente utilizza la versione principale della libreria client Go Pub/Sub (v2). Se utilizzi ancora la libreria v1, consulta la guida alla migrazione alla v2. Per visualizzare un elenco di esempi di codice della versione 1, consulta gli esempi di codice deprecati.

Prima di provare questo esempio, segui le istruzioni di configurazione di Go nella guida rapida all'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API Pub/Sub 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

Prima di provare questo esempio, segui le istruzioni di configurazione di Java nella guida rapida all'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API Java di Pub/Sub.

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

Prima di provare questo esempio, segui le istruzioni di configurazione di Python nella guida rapida all'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API Pub/Sub 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

Prima di provare questo esempio, segui le istruzioni di configurazione di Node.js nella guida rapida all'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API Pub/Sub 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

Prima di provare questo esempio, segui le istruzioni di configurazione di Node.js nella guida rapida all'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API Pub/Sub 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'esempio seguente utilizza la libreria client Ruby Pub/Sub v3. Se utilizzi ancora la libreria v2, consulta la guida alla migrazione alla v3. Per visualizzare un elenco di esempi di codice Ruby v2, consulta gli esempi di codice deprecati.

Prima di provare questo esempio, segui le istruzioni di configurazione di Ruby nella guida rapida all'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API Pub/Sub 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

Prima di provare questo esempio, segui le istruzioni di configurazione di PHP nella guida rapida all'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API Pub/Sub 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');
}

Rust

Prima di provare questo esempio, segui le istruzioni di configurazione di Rust nella guida rapida all'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API Pub/Sub Rust.

use google_cloud_pubsub::client::SubscriptionAdmin;

pub async fn sample(
    client: &SubscriptionAdmin,
    project_id: &str,
    topic_id: &str,
    subscription_id: &str,
) -> anyhow::Result<()> {
    let subscription_name = format!("projects/{project_id}/subscriptions/{subscription_id}");
    let topic_name = format!("projects/{project_id}/topics/{topic_id}");

    let subscription = client
        .create_subscription()
        .set_name(subscription_name)
        .set_topic(topic_name)
        .set_enable_exactly_once_delivery(true)
        .send()
        .await?;

    println!("successfully created subscription {subscription:?}");
    Ok(())
}

Monitorare gli abbonamenti con consegna "exactly-once"

La metrica subscription/exactly_once_warning_count registra il numero di eventi che possono portare a possibili nuove consegne (valide o duplicate). Questa metrica conteggia il numero di volte in cui Pub/Sub non riesce a elaborare le richieste associate agli ID riconoscimento (richiesta ModifyAckDeadline o acknowledgment). I motivi del mancato caricamento potrebbero essere basati sul server o sul client. Ad esempio, se il livello di persistenza utilizzato per gestire le informazioni di distribuzione esattamente una volta non è disponibile, si tratterebbe di un evento basato sul server. Se il client tenta di confermare un messaggio con un ID di conferma non valido, si tratterà di un evento basato sul client.

Comprendere la metrica

subscription/exactly_once_warning_count acquisisce eventi che potrebbero o meno portare a nuove consegne effettive e può essere rumoroso in base al comportamento del cliente. Ad esempio, le richieste acknowledgment o ModifyAckDeadline ripetute con ID riconoscimento non validi aumentano ripetutamente la metrica.

Anche le seguenti metriche sono utili per comprendere il comportamento dei clienti:

  • La metrica subscription/expired_ack_deadlines_count mostra il numero di scadenze dell'ID riconoscimento. La scadenza degli ID di conferma può causare errori sia per le richieste ModifyAckDeadline che per quelle acknowledgment.

  • La metrica service.serviceruntime.googleapis.com/api/request_count può essere utilizzata per acquisire gli errori delle richieste ModifyAckDeadline o acknowledgment nei casi in cui le richieste raggiungono Google Cloud ma non Pub/Sub. Esistono errori che questa metrica non acquisisce, ad esempio quando i client sono disconnessi da Google Cloud.

Nella maggior parte dei casi di eventi di errore che possono essere riprovati, le librerie client supportate riprovano automaticamente la richiesta.

Quote

Le sottoscrizioni con consegna "exactly-once" sono soggette a requisiti di quota aggiuntivi. Queste quote vengono applicate a:

  • Numero di messaggi utilizzati dalle sottoscrizioni con la funzionalità di consegna esattamente una volta attivata per regione.
  • Numero di messaggi riconosciuti o la cui scadenza è stata estesa quando si utilizzano sottoscrizioni con la consegna exactly-once abilitata per regione.

Per saperne di più su queste quote, consulta la tabella nell'argomento Quote.

Consegna "exactly-once" e sottoscrizioni ordinate

Pub/Sub supporta la consegna "exactly-once" con consegna ordinata.

Quando utilizzi l'ordinamento con la consegna "exactly-once", Pub/Sub prevede che gli ACK siano in ordine. Se gli ACK non sono in ordine, il servizio non riesce a gestire le richieste con errori temporanei. Se la scadenza di conferma scade prima di una conferma in ordine per la consegna, il client riceverà una nuova consegna del messaggio. Per questo motivo, quando utilizzi l'ordinamento con la distribuzione esatta, la velocità effettiva del client è limitata a un ordine di migliaia di messaggi al secondo.

Consegna "exactly-once" e sottoscrizioni push

Pub/Sub supporta la consegna "exactly-once" solo con le sottoscrizioni pull.

I client che utilizzano i messaggi delle sottoscrizioni push confermano la ricezione dei messaggi rispondendo alle richieste push con una risposta positiva. Tuttavia, i client non sanno se la sottoscrizione Pub/Sub ha ricevuto la risposta e l'ha elaborata. Questo è diverso dalle sottoscrizioni pull, in cui le richieste di riconoscimento vengono avviate dai client e la sottoscrizione Pub/Sub risponde se la richiesta è stata elaborata correttamente. Per questo motivo, la semantica della consegna "exactly-once" non è adatta alle sottoscrizioni push.

Cose da sapere

  • Se la scadenza di riconoscimento non viene specificata al momento di CreateSubscription, le sottoscrizioni con la consegna "exactly-once" abilitata avranno una scadenza di riconoscimento predefinita di 60 secondi.

  • Le scadenze di riconoscimento predefinite più lunghe sono utili per evitare la nuova consegna causata da eventi di rete. Le librerie client supportate non utilizzano la scadenza di conferma dell'abbonamento predefinita.

  • Le sottoscrizioni con consegna "exactly-once" hanno una latenza dalla pubblicazione alla sottoscrizione significativamente più elevata rispetto alle sottoscrizioni regolari.

  • Se hai bisogno di throughput elevato, i client di distribuzione exactly-once devono utilizzare anche lo streaming pull.

  • Una sottoscrizione potrebbe ricevere più copie dello stesso messaggio a causa di duplicati lato pubblicazione, anche con la consegna exactly-once abilitata. I duplicati lato pubblicazione possono essere dovuti a più tentativi di pubblicazione unici da parte del client di pubblicazione o del servizio Pub/Sub. Più pubblicazioni uniche da parte del client di pubblicazione, nei vari tentativi, comportano nuove consegne con ID messaggio diversi. Più pubblicazioni uniche da parte del servizio Pub/Sub, per rispondere a una richiesta di pubblicazione del client, comportano riconsegne con gli stessi ID messaggio.

  • Puoi riprovare in caso di errori in subscription/exactly_once_warning_count e le librerie client supportate riprovano automaticamente. Tuttavia, gli errori relativi a ID di riconoscimento non validi non possono essere riprovati.