Como ordenar mensagens

Esta página explica como receber mensagens em ordem.

Para mais informações sobre como receber mensagens, consulte a visão geral do assinante.

Recebimento de mensagens em ordem

Se as mensagens tiverem a mesma chave de ordem e estiverem na mesma região, é possível ativar a ordenação e receber as mensagens na ordem que o serviço Pub/Sub as recebe.

O Pub/Sub entrega cada mensagem pelo menos uma vez, para que o serviço do Pub/Sub possa reenviar as mensagens. Quando você recebe mensagens em ordem e o serviço Pub/Sub entrega uma mensagem com uma chave de ordem, o Pub/Sub mantém a ordem também reenviando as mensagens subsequentes com a mesma chave de ordem. O serviço do Pub/Sub entrega essas mensagens novamente na ordem em que elas foram recebidas originalmente.

Quando o serviço do Pub/Sub reenvia uma mensagem com uma chave de ordem, o serviço do Pub/Sub também reenvia cada mensagem subsequente com a mesma chave de ordem, incluindo as mensagens confirmadas. Se a ordem das mensagens e um tópico de mensagens inativas estiverem ativados em uma assinatura, isso poderá não ser verdadeiro, já que o Pub/Sub encaminha mensagens para tópicos de mensagens inativas em com base no melhor esforço. Quando as mensagens reenviadas são recebidas, é necessário confirmar essas mensagens novamente. Não há garantia de que as mensagens subsequentes serão enviadas sem que as anteriores sejam confirmadas.

Como ativar a ordem das mensagens

Para receber as mensagens em ordem, defina a propriedade de ordenação das mensagens na assinatura que recebe as mensagens. O recebimento de mensagens pode aumentar a latência.

É possível definir a propriedade de ordem de mensagens ao criar uma assinatura usando o Console do Cloud, a ferramenta de linha de comando gcloud ou a API Pub/Sub.

Console

Para criar uma assinatura com a propriedade de ordenação de mensagens, siga estas etapas:

  1. No Console do Cloud, acesse a página Assinaturas.

    Acessar a página "Assinaturas"

  2. Clique em Criar assinatura.

  3. Insira um ID de assinatura.

  4. Escolha um tópico para receber as mensagens.

  5. Na seção Ordem das mensagens, selecione Ordenar mensagens com uma chave de ordem.

  6. Clique em Criar.

gcloud

Para criar uma assinatura com a propriedade de ordenação de mensagens, use o comando gcloud pubsub subscriptions create e a sinalização --enable-message-ordering:

gcloud pubsub subscriptions create SUBSCRIPTION_ID \
  --enable-message-ordering

Substitua SUBSCRIPTION_ID pelo ID da assinatura.

Se a solicitação for bem-sucedida, a linha de comando exibirá uma confirmação:

Created subscription [SUBSCRIPTION_ID].

REST

Para criar uma assinatura com a propriedade de ordenação de mensagens, envie uma solicitação PUT como a seguinte:

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

Substitua:

  • PROJECT_ID: o ID do projeto com o tópico.
  • SUBSCRIPTION_ID: o ID da assinatura.

No corpo da solicitação, especifique o seguinte:

{
  "topic": TOPIC_ID,
  "enableMessageOrdering": true,
}

Substitua TOPIC_ID pelo ID do tópico a ser anexado à assinatura.

Se a solicitação for bem-sucedida, a resposta será a assinatura no formato JSON:

{
  "name": projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID,
  "topic": projects/PROJECT_ID/topics/TOPIC_ID,
  "enableMessageOrdering": true,
}

C++

Antes de tentar esse exemplo, siga as instruções de configuração do C++ em Guia de início rápido: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Pub/Sub C++.

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

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

C#

Antes de tentar esse exemplo, siga as instruções de configuração do C# em Guia de início rápido: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Pub/Sub C#.


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

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

        var subscriptionRequest = new Subscription
        {
            SubscriptionName = subscriptionName,
            TopicAsTopicName = topicName,
            EnableMessageOrdering = 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

Antes de tentar esse exemplo, siga as instruções de configuração do Go em Guia de início rápido: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Pub/Sub Go.

import (
	"context"
	"fmt"
	"io"
	"time"

	"cloud.google.com/go/pubsub"
)

func createWithOrdering(w io.Writer, projectID, subID string, topic *pubsub.Topic) error {
	// projectID := "my-project-id"
	// subID := "my-sub"
	// topic of type https://godoc.org/cloud.google.com/go/pubsub#Topic
	ctx := context.Background()
	client, err := pubsub.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("pubsub.NewClient: %v", err)
	}
	defer client.Close()

	// Message ordering can only be set when creating a subscription.
	sub, err := client.CreateSubscription(ctx, subID, pubsub.SubscriptionConfig{
		Topic:                 topic,
		AckDeadline:           20 * time.Second,
		EnableMessageOrdering: true,
	})
	if err != nil {
		return fmt.Errorf("CreateSubscription: %v", err)
	}
	fmt.Fprintf(w, "Created subscription: %v\n", sub)
	return nil
}

Java

Antes de tentar essa amostra, siga as instruções de configuração do Java em Guia de início rápido: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Pub/Sub 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 CreateSubscriptionWithOrdering {
  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";

    createSubscriptionWithOrderingExample(projectId, topicId, subscriptionId);
  }

  public static void createSubscriptionWithOrderingExample(
      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())
                  // Set message ordering to true for ordered messages in the subscription.
                  .setEnableMessageOrdering(true)
                  .build());

      System.out.println("Created a subscription with ordering: " + subscription.getAllFields());
    }
  }
}

Node.js

Antes de tentar essa amostra, siga as instruções de configuração do Node.js em Guia de início rápido: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Pub/Sub Node.js.

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const topicName = 'YOUR_TOPIC_NAME';
// const subscriptionName = 'YOUR_SUBSCRIPTION_NAME';

// 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 createSubscriptionWithOrdering() {
  // Creates a new subscription
  await pubSubClient.topic(topicName).createSubscription(subscriptionName, {
    enableMessageOrdering: true,
  });
  console.log(
    `Created subscription ${subscriptionName} with ordering enabled.`
  );
  console.log(
    'To process messages in order, remember to add an ordering key to your messages.'
  );
}

createSubscriptionWithOrdering().catch(console.error);

Python

Antes de tentar esse exemplo, siga as instruções de configuração do Python em Guia de início rápido: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da 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_message_ordering": True,
        }
    )
    print(f"Created subscription with ordering: {subscription}")

Ruby

Antes de tentar esse exemplo, siga as instruções de configuração do Ruby em Guia de início rápido: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Pub/Sub Ruby.

# topic_id        = "your-topic-id"
# subscription_id = "your-subscription-id"
require "google/cloud/pubsub"

pubsub = Google::Cloud::Pubsub.new

topic        = pubsub.topic topic_id
subscription = topic.subscribe subscription_id,
                               message_ordering: true

puts "Pull subscription #{subscription_id} created with message ordering."

Depois que a propriedade de ordem da mensagem é definida, o serviço Pub/Sub entrega mensagens com a mesma chave de ordem na ordem em que o serviço Pub/Sub recebe as mensagens. Por exemplo, se um editor envia duas mensagens com a mesma chave de ordem, o serviço do Pub/Sub entrega a mensagem mais antiga primeiro.