Nachrichten in eine Reihenfolge bringen

Die Nachrichtenreihenfolge ist ein Pub/Sub-Feature, mit dem du Nachrichten in deinen Abonnentenclients in der Reihenfolge empfangen kannst, in der sie von den Publisher-Clients veröffentlicht wurden.

Angenommen, ein Publisher-Client in einer Region veröffentlicht die Nachrichten 1, 2, und 3 in der richtigen Reihenfolge. Bei der Nachrichtenreihenfolge empfängt der Abonnentenclient die veröffentlichten Nachrichten in derselben Reihenfolge. Um in der richtigen Reihenfolge ausgeliefert zu werden, muss der Verlag oder Webpublisher muss der Client die Nachrichten im selben region [Region] an.

Die Nachrichtensortierung ist eine nützliche Funktion für Szenarien wie die Erfassung von Datenbankänderungen, das Tracking von Nutzersitzungen und Streaminganwendungen, bei denen die chronologische Reihenfolge der Ereignisse wichtig ist.

Auf dieser Seite wird das Konzept der Nachrichtensortierung erläutert und beschrieben, wie Sie Ihre Abonnenten-Clients so einrichten, dass sie Nachrichten in der richtigen Reihenfolge erhalten. Informationen zum Konfigurieren deiner Publisher-Clients für die Nachrichtensortierung findest du unter Sortierungsschlüssel verwenden, um eine Nachricht zu veröffentlichen.

Nachrichtenreihenfolge

Die Reihenfolge in Pub/Sub wird so festgelegt:

  • Anordnungsschlüssel: Dies ist ein String, der in den Pub/Sub-Nachrichtenmetadaten. Sie stellen die Entität dar, für die Nachrichten geordnet werden müssen. Der Sortierschlüssel kann bis zu 1 KB lang sein. Wenn Sie eine Reihe von Nachrichten in einer Region erhalten möchten, müssen Sie alle Nachrichten mit demselben Sortierungsschlüssel in derselben Region veröffentlichen. Einige Beispiele für die Sortierung Schlüssel sind Kundennummern und der Primärschlüssel einer Zeile in einer Datenbank.

    Der Veröffentlichungsdurchsatz pro Bestellschlüssel ist auf 1 Mbit/s begrenzt. Die Der Durchsatz aller Bestellschlüssel zu einem Thema ist auf das Kontingent beschränkt in einer Veröffentlichungsregion verfügbar sind. Dieses Limit kann auf viele GBps erhöht werden.

    Ein Sortierungsschlüssel entspricht nicht einer Partition in einer partitionsbasierten Nachrichtensystem kommunizieren, da Bestellschlüssel voraussichtlich eine viel höhere als Partitionen.

  • Nachrichtenreihenfolge aktivieren: Dies ist eine Aboeinstellung. Wenn für ein Abo die Nachrichtenreihenfolge aktiviert ist, erhalten die Abonnentenclients Nachrichten, die in derselben Region mit demselben Reihenfolgeschlüssel veröffentlicht wurden, in der Reihenfolge, in der sie vom Dienst empfangen wurden. Sie müssen diese Einstellung im Abo aktivieren.

    Angenommen, Sie haben zwei Abos A und B, die mit demselben Thema T verknüpft sind. Bei Abo A ist die Nachrichtenreihenfolge aktiviert und bei Abo B nicht. In dieser Architektur erhalten sowohl Abo A als auch Abo B dieselben Nachrichten vom Thema T. Wenn Sie Nachrichten mit Reihenfolgeschlüsseln in derselben Region veröffentlichen, empfängt Abo A die Nachrichten in der Reihenfolge, in der sie veröffentlicht wurden. Im Gegensatz dazu erhält Abo B die Nachrichten ohne erwartete Reihenfolge.

Im Allgemeinen gilt: Wenn Ihre Lösung erfordert, dass Publisher-Kunden sowohl bestellte als auch nicht sortierte Nachrichten erstellen, separate Themen erstellen, eins für sortierte Nachrichten und andere für ungeordnete Nachrichten.

Überlegungen bei der Verwendung von sortierten Nachrichten

Die folgende Liste enthält wichtige Informationen zum Verhalten von geordneten Nachrichten in Pub/Sub:

  • Sortierung innerhalb des Schlüssels: Nachrichten, die mit demselben Reihenfolgeschlüssel veröffentlicht werden, werden in der Regel in der richtigen Reihenfolge empfangen. Angenommen, Sie veröffentlichen für den Sortierungsschlüssel A die Nachrichten 1, 2 und 3. Wenn die Sortierung aktiviert ist, wird „1“ voraussichtlich vor „2“ und „2“ voraussichtlich vor „3“ ausgeliefert.

  • Schlüsselübergreifende Reihenfolge: Nachrichten, die mit unterschiedlichen Reihenfolgeschlüsseln veröffentlicht wurden, werden nicht in der richtigen Reihenfolge eingehen. Angenommen, Sie haben die Bestellschlüssel A und B. Für Schlüssel A werden die Nachrichten 1 und 2 der Reihe nach veröffentlicht. Zum Bestellen Schlüssel B werden die Botschaften 3 und 4 der Reihe nach veröffentlicht. Nachricht 1 kann jedoch vor oder nach Nachricht 4 eintreffen.

  • Wiedervorlage von Nachrichten: Pub/Sub sendet jede Nachricht mindestens einmal, sodass der Pub/Sub-Dienst Nachrichten möglicherweise wiederholt sendet. Wenn eine Nachricht noch einmal gesendet wird, werden auch alle nachfolgenden Nachrichten für diesen Schlüssel noch einmal gesendet, auch bestätigte. Angenommen, ein Abonnentenclient empfängt Nachrichten 1, 2 und 3 für einen bestimmten Reihenfolgenschlüssel. Wenn Nachricht 2 erneut zugestellt wird (weil der die Bestätigungsfrist abgelaufen ist oder die Best-Effort-Bestätigung nicht erfolgreich war in Pub/Sub beibehalten, wird Nachricht 3 ebenfalls noch einmal zugestellt. Wenn sowohl die Nachrichtenreihenfolge als auch ein Thema für unzustellbare Nachrichten für ein Abo aktiviert sind, ist dies möglicherweise nicht der Fall, da Pub/Sub Nachrichten an Themen für unzustellbare Nachrichten auf Best-Effort-Basis weiterleitet.

  • Bestätigungsverzögerungen und Themen für unzustellbare Nachrichten: Unbestätigte Nachrichten für einen bestimmten Sortierschlüssel können die Zustellung von Nachrichten für andere Sortierschlüssel verzögern, insbesondere bei Serverneustarts oder Verkehrsänderungen. Um die Ordnung in diesen Ereignissen aufrechtzuerhalten, sollten Sie alle Nachrichten. Wenn eine zeitnahe Bestätigung nicht möglich ist, sollten Sie ein Thema für unzustellbare Nachrichten verwenden, um eine unbegrenzte Nachrichtenspeicherung zu verhindern. Beachten Sie, dass die Bestellung werden möglicherweise nicht beibehalten, wenn Nachrichten in ein Thema für unzustellbare Nachrichten geschrieben werden.

  • Nachrichtenaffinität (streamingPull-Clients): Nachrichten für denselben Schlüssel werden in der Regel an denselben streamingPull-Abonnentenclient gesendet. Eine Affinität wird erwartet, wenn Nachrichten für einen Reihenfolgeschlüssel an einen bestimmten Abonnentenclient ausstehend sind. Wenn keine ausstehenden Nachrichten vorhanden sind, kann die Affinität für das Load Balancing oder die Clientverbindungen geändert werden.

    Damit die Verarbeitung auch bei potenziellen Affinitätsänderungen reibungslos abläuft, muss deine StreamingPull-Anwendung so konzipiert sein, dass sie Nachrichten in jedem Client für einen bestimmten Sortierschlüssel verarbeiten kann.

  • Integration with Dataflow: Nachrichtensortierung nicht aktivieren für wenn Sie Dataflow mit Pub/Sub Dataflow hat einen eigenen Mechanismus für die gesamte Reihenfolge der Nachrichten, wodurch alle Nachrichten in chronologischer Reihenfolge Teil von Windowing-Vorgängen. Diese Sortierungsmethode unterscheidet sich vom Pub/Sub-Schlüsselbasierten Ansatz. Sortierungsschlüssel verwenden mit Dataflow die Pipelineleistung verringern.

  • Autoscaling: Die geordnete Bereitstellung von Pub/Sub wird auf Milliarden von Sortierschlüsseln. Eine größere Anzahl von Reihenfolgeschlüsseln ermöglicht eine parallelere Zustellung an Abonnenten, da die Sortierung auf alle Nachrichten mit demselben Reihenfolgeschlüssel angewendet wird.

Die Lieferung auf Bestellung hat jedoch einige Nachteile. Im Vergleich zu ungeordnet die geordnete Auslieferung die Veröffentlichungsverfügbarkeit geringfügig verringern und die Latenz bei der End-to-End-Nachrichtenzustellung erhöhen. Im Fall der bestellten Lieferung Der Failover erfordert eine Koordination, um sicherzustellen, dass die Nachrichten geschrieben und gelesen werden. in die richtige Reihenfolge bringen.

Weitere Informationen zur Nachrichtensortierung finden Sie in den folgenden Best Practices:

Verhalten des Abonnentenclients für die Nachrichtenreihenfolge

Abonnentenclients erhalten Nachrichten in der Reihenfolge, in der sie in einer bestimmten Region veröffentlicht wurden. Pub/Sub unterstützt verschiedene Möglichkeiten zum Empfangen von Nachrichten, z. B. Abonnentenclients, die mit Pull- und Push-Abos verbunden sind. Die Clientbibliotheken verwenden streamPull (ausgenommen PHP).

Weitere Informationen zu diesen Abotypen finden Sie unter Abotyp auswählen.

In den folgenden Abschnitten wird erläutert, was der Empfang von Nachrichten in der richtigen Reihenfolge für die einzelnen Arten von Abonnentenclients bedeutet.

StreamingPull-Abonnentenclients

Wenn Sie die Clientbibliotheken mit streamingPull verwenden, müssen Sie einen Nutzer-Callback angeben, der ausgeführt wird, wenn ein Abonnentenclient eine Nachricht empfängt. Bei Clientbibliotheken wird der Callback für jeden beliebigen Reihenfolgenschlüssel bis zum Ende für Nachrichten in der richtigen Reihenfolge ausgeführt. Wenn die Nachrichten innerhalb dieses Callbacks bestätigt wurden, erfolgen alle Berechnungen für eine Nachricht in der richtigen Reihenfolge. Wenn der Nutzer-Callback jedoch andere asynchrone Aufgaben für Nachrichten plant, muss der Abonnentenclient dafür sorgen, dass die asynchronen Aufgaben in der richtigen Reihenfolge ausgeführt werden. Eine Möglichkeit besteht darin, Nachrichten zu einer lokalen Arbeitswarteschlange hinzuzufügen, der Reihenfolge nach verarbeitet werden.

Pull-Abonnenten

Für Abonnentenclients, die mit Pull-Abos verbunden sind, wird bei der Pub/Sub-Nachrichtensortierung Folgendes unterstützt:

  • Alle Nachrichten für einen Reihenfolgeschlüssel in der PullResponse sind in der Liste in der richtigen Reihenfolge.

  • Nur ein Batch von Nachrichten darf für einen Sortierungsschlüssel ausstehend sein auf einmal ansehen.

Die Anforderung, dass jeweils nur ein Nachrichten-Batch ausstehend sein darf, ist für die geordnete Zustellung erforderlich, da der Pub/Sub-Dienst nicht für den Erfolg oder die Latenz der Antwort garantieren kann, die er für den Pull-Request eines Abonnenten sendet.

Push-Abonnenten

Die Einschränkungen für Push-Nachrichten sind noch strenger als die für Pull-Nachrichten. Bei einem Push-Abo unterstützt Pub/Sub nur eine ausstehende für jeden Bestellschlüssel auf einmal. Jede Nachricht wird als separate Anfrage an einen Push-Endpunkt gesendet. Das Senden der Anfragen parallel würde also dasselbe Problem verursachen wie das Senden mehrerer Nachrichtenbatches für denselben Reihenfolgenschlüssel, um Abonnenten gleichzeitig abzurufen. Push-Abos sind möglicherweise keine gute Wahl für Themen, in denen Nachrichten häufig mit demselben Reihenfolgeschlüssel veröffentlicht werden oder bei dem die Latenz ist extrem wichtig.

Abonnentenclients exportieren

Exportierte Abos unterstützen sortierte Nachrichten. Bei BigQuery-Abos werden Nachrichten mit demselben Reihenfolgeschlüssel nacheinander in die BigQuery-Tabelle geschrieben. Bei Cloud Storage-Abos Nachrichten mit demselben Reihenfolgeschlüssel werden möglicherweise nicht alle in dieselbe Datei geschrieben. Innerhalb derselben Datei sind Nachrichten für einen Sortierungsschlüssel sortiert. Wann? über mehrere Dateien verteilt sind, können spätere Nachrichten für einen Datei mit einem Namen, der einen früheren Zeitstempel hat als der Zeitstempel im Namen die Datei mit den vorherigen Nachrichten.

Nachrichtenreihenfolge aktivieren

Damit die Nachrichten der Reihe nach empfangen werden, legen Sie das Attribut für die Nachrichtenreihenfolge für das Abo fest, über das Sie Nachrichten erhalten. Das Empfangen von Nachrichten der Reihe nach kann die Latenz erhöhen. Sie können die Eigenschaft für die Nachrichtenreihenfolge nicht mehr ändern, nachdem Sie Abo erstellen.

Sie können das Attribut für die Nachrichtenreihenfolge festlegen, wenn Sie ein Abo in der Google Cloud Console, der Google Cloud CLI oder der Pub/Sub API erstellen.

Console

So erstellen Sie ein Abo mit dem Attribut für die Nachrichtenreihenfolge:

  1. Öffnen Sie in der Google Cloud Console die Seite Abos.

Zu den Abos

  1. Klicken Sie auf Abo erstellen.

  2. Geben Sie eine Abo-ID ein.

  3. Wählen Sie ein Thema aus, von dem Sie Nachrichten erhalten möchten.

  4. Wählen Sie im Abschnitt Nachrichtenreihenfolge die Option Nachrichten mit einem Reihenfolgeschlüssel sortieren aus.

  5. Klicken Sie auf Erstellen.

gcloud

Verwenden Sie zum Erstellen eines Abos mit dem Attribut für die Nachrichtenreihenfolge den Befehl gcloud pubsub subscriptions create und das Flag --enable-message-ordering:

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

Ersetzen Sie SUBSCRIPTION_ID durch die ID des Abos.

Wenn die Anfrage erfolgreich ist, wird in der Befehlszeile eine Bestätigung angezeigt:

Created subscription [SUBSCRIPTION_ID].

REST

Senden Sie eine PUT, um ein Abo mit der Eigenschaft „Nachrichtenreihenfolge“ zu erstellen. wie folgt aussehen:

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

Ersetzen Sie Folgendes:

  • PROJECT_ID: Projekt-ID des Projekts mit dem Thema
  • SUBSCRIPTION_ID: die ID des Abos

Geben Sie im Anfragetext Folgendes an:

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

Ersetzen Sie TOPIC_ID durch die ID des Themas, das an das Abo angehängt werden soll.

Wenn die Anfrage erfolgreich ist, ist die Antwort das Lite-Abo im JSON-Format:

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

C++

Bevor Sie dieses Beispiel testen, folgen Sie der Einrichtungsanleitung für C++ in der Kurzanleitung: Clientbibliotheken verwenden. Weitere Informationen finden Sie in der Referenzdokumentation zur Pub/Sub C++ API.

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_message_ordering(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#

Bevor Sie dieses Beispiel testen, folgen Sie der Einrichtungsanleitung für C# in der Schnellstart-Anleitung: Clientbibliotheken verwenden. Weitere Informationen finden Sie in der Referenzdokumentation zu Pub/Sub C# API.


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

public class CreateSubscriptionWithOrderingSample
{
    public Subscription CreateSubscriptionWithOrdering(string projectId, string topicId, string subscriptionId)
    {
        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

Bevor Sie dieses Beispiel testen, folgen Sie der Einrichtungsanleitung für Go in der Schnellstart-Anleitung: Clientbibliotheken verwenden. Weitere Informationen finden Sie in der Referenzdokumentation zu Pub/Sub Go API.

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: %w", 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: %w", err)
	}
	fmt.Fprintf(w, "Created subscription: %v\n", sub)
	return nil
}

Java

Bevor Sie dieses Beispiel testen, folgen Sie der Einrichtungsanleitung für Java in der Kurzanleitung: Clientbibliotheken verwenden. Weitere Informationen finden Sie in der Referenzdokumentation zu Pub/Sub Java API.

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

Bevor Sie dieses Beispiel testen, folgen Sie der Einrichtungsanleitung für PHP in der Schnellstart-Anleitung: Clientbibliotheken verwenden. Weitere Informationen finden Sie in der Referenzdokumentation zu Pub/Sub Node.js API.

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

Node.js

Bevor Sie dieses Beispiel testen, folgen Sie der Einrichtungsanleitung für PHP in der Schnellstart-Anleitung: Clientbibliotheken verwenden. Weitere Informationen finden Sie in der Referenzdokumentation zu Pub/Sub Node.js API.

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

Python

Bevor Sie dieses Beispiel testen, folgen Sie der Einrichtungsanleitung für Python in der Schnellstart-Anleitung: Clientbibliotheken verwenden. Weitere Informationen finden Sie in der Referenzdokumentation zu Pub/Sub Python API.

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

Bevor Sie dieses Beispiel testen, folgen Sie der Einrichtungsanleitung für Ruby in der Schnellstart-Anleitung: Clientbibliotheken verwenden. Weitere Informationen finden Sie in der Referenzdokumentation zu Pub/Sub Ruby API.

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

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."

Nächste Schritte