1. Einführung
In diesem Codelab verwenden Sie gRPC-Python, um einen Client und einen Server zu erstellen, die die Grundlage einer in Python geschriebenen Routenplanungsanwendung bilden.
Am Ende des Tutorials haben Sie einen Client, der über gRPC eine Verbindung zu einem Remote-Server herstellt, um den Namen oder die Postanschrift des Objekts an bestimmten Koordinaten auf einer Karte abzurufen. Eine vollwertige Anwendung könnte dieses Client-Server-Design verwenden, um POIs entlang einer Route aufzulisten oder zusammenzufassen.
Der Dienst wird in einer Protocol Buffers-Datei definiert, die zum Generieren von Boilerplate-Code für den Client und den Server verwendet wird, damit sie miteinander kommunizieren können. So sparen Sie Zeit und Aufwand bei der Implementierung dieser Funktion.
Dieser generierte Code kümmert sich nicht nur um die Komplexität der Kommunikation zwischen Server und Client, sondern auch um die Serialisierung und Deserialisierung von Daten.
Lerninhalte
- Wie Sie Protocol Buffers zum Definieren einer Dienst-API verwenden.
- Hier erfahren Sie, wie Sie einen gRPC-basierten Client und Server aus einer Protocol Buffers-Definition mithilfe der automatischen Codegenerierung erstellen.
- Kenntnisse der Client-Server-Kommunikation mit gRPC
Dieses Codelab richtet sich an Python-Entwickler, die neu in gRPC sind oder eine Auffrischung von gRPC wünschen, sowie an alle anderen, die sich für die Entwicklung verteilter Systeme interessieren. Es sind keine Vorkenntnisse in gRPC erforderlich.
2. Hinweis
Voraussetzungen
- Python 3.9 oder höher. Wir empfehlen Python 3.13. Plattformspezifische Installationsanleitungen finden Sie unter Python-Einrichtung und ‑Verwendung. Alternativ können Sie mit Tools wie uv oder pyenv eine Nicht-System-Python-Version installieren.
- pip zum Installieren von Python-Paketen.
- venv zum Erstellen virtueller Python-Umgebungen.
Die Pakete ensurepip
und venv
sind Teil der Python-Standardbibliothek und in der Regel standardmäßig verfügbar.
Einige Debian-basierte Distributionen (einschließlich Ubuntu) schließen sie jedoch bei der Weitergabe von Python aus. Führen Sie Folgendes aus, um die Pakete zu installieren:
sudo apt install python3-pip python3-venv
Code abrufen
Um Ihnen den Einstieg zu erleichtern, wird in diesem Codelab ein vorgefertigtes Quellcode-Gerüst bereitgestellt. In den folgenden Schritten wird beschrieben, wie Sie die Anwendung fertigstellen, einschließlich der gRPC-Code-Generierung mit dem grpc_tools.protoc
-Compiler-Plug-in für Protocol Buffer.
grpc-codelabs
Der Gerüstquellcode für dieses Codelab ist im Verzeichnis codelabs/grpc-python-getting-started/start_here verfügbar. Wenn Sie den Code nicht selbst implementieren möchten, finden Sie den vollständigen Quellcode im Verzeichnis completed
.
Erstellen Sie zuerst das Arbeitsverzeichnis für das Codelab und wechseln Sie in dieses Verzeichnis:
mkdir grpc-python-getting-started && cd grpc-python-getting-started
Laden Sie das Codelab herunter und extrahieren Sie es:
curl -sL https://github.com/grpc-ecosystem/grpc-codelabs/archive/refs/heads/v1.tar.gz \
| tar xvz --strip-components=4 \
grpc-codelabs-1/codelabs/grpc-python-getting-started/start_here
Alternativ können Sie die ZIP-Datei herunterladen, die nur das Codelab-Verzeichnis enthält, und sie manuell entpacken.
3. Dienst definieren
Als Erstes müssen Sie den gRPC-Dienst der Anwendung, die zugehörige RPC-Methode sowie die Anfrage- und Antwortnachrichtentypen mit der Protocol Buffers-Schnittstellendefinitionssprache definieren. Ihr Dienst bietet Folgendes:
- Eine RPC-Methode namens
GetFeature
, die vom Server implementiert und vom Client aufgerufen wird. - Die Nachrichtentypen
Point
undFeature
sind Datenstrukturen, die beim Verwenden derGetFeature
-Methode zwischen dem Client und dem Server ausgetauscht werden. Der Client stellt Kartenkoordinaten alsPoint
in seinerGetFeature
-Anfrage an den Server bereit und der Server antwortet mit einem entsprechendenFeature
, das beschreibt, was sich an diesen Koordinaten befindet.
Diese RPC-Methode und ihre Nachrichtentypen werden alle in der Datei protos/route_guide.proto
des bereitgestellten Quellcodes definiert.
Protocol Buffers werden allgemein als Protobuf bezeichnet. Weitere Informationen zur gRPC-Terminologie finden Sie unter Core concepts, architecture, and lifecycle.
Mitteilungstypen
Definieren Sie zuerst den Nachrichtentyp Point
in der Datei protos/route_guide.proto
des Quellcodes. Ein Point
stellt ein Paar aus Breiten- und Längengrad auf einer Karte dar. Verwenden Sie für dieses Codelab Ganzzahlen für die Koordinaten:
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
Die Zahlen 1
und 2
sind eindeutige ID-Nummern für die einzelnen Felder in der message
-Struktur.
Als Nächstes definieren Sie den Nachrichtentyp Feature
. Bei einem Feature
wird ein string
-Feld für den Namen oder die Postanschrift von etwas an einem Standort verwendet, der durch ein Point
angegeben wird:
message Feature {
// The name or address of the feature.
string name = 1;
// The point where the feature is located.
Point location = 2;
}
Servicemethode
Die Datei route_guide.proto
hat eine service
-Struktur mit dem Namen RouteGuide
, die eine oder mehrere Methoden definiert, die vom Dienst der Anwendung bereitgestellt werden.
Fügen Sie die Methode rpc
GetFeature
in die Definition von RouteGuide
ein. Wie bereits erwähnt, wird mit dieser Methode der Name oder die Adresse eines Orts anhand einer bestimmten Menge von Koordinaten ermittelt. Lassen Sie also von GetFeature
ein Feature
für ein bestimmtes Point
zurückgeben:
service RouteGuide {
// Definition of the service goes here
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
}
Dies ist eine unäre RPC-Methode: ein einfacher RPC, bei dem der Client eine Anfrage an den Server sendet und auf eine Antwort wartet, genau wie bei einem lokalen Funktionsaufruf.
4. Client- und Servercode generieren
Als Nächstes generieren Sie den Boilerplate-gRPC-Code für Client und Server aus der Datei .proto
mit dem Protokollpuffer-Compiler.
Für die Generierung von gRPC-Python-Code haben wir grpcio-tools erstellt. Dazu gehören:
- Der reguläre protoc-Compiler, der Python-Code aus
message
-Definitionen generiert. - gRPC-Protobuf-Plug-in, das Python-Code (Client- und Server-Stubs) aus den
service
-Definitionen generiert.
Wir installieren das Python-Paket grpcio-tools
mit pip. Erstellen wir eine neue virtuelle Python-Umgebung (venv), um die Abhängigkeiten Ihres Projekts von den Systempaketen zu isolieren:
python3 -m venv --upgrade-deps .venv
So aktivieren Sie die virtuelle Umgebung in der Bash-/Zsh-Shell:
source .venv/bin/activate
Informationen zu Windows und nicht standardmäßigen Shells finden Sie in der Tabelle unter https://docs.python.org/3/library/venv.html#how-venvs-work.
Installieren Sie als Nächstes grpcio-tools (dadurch wird auch das Paket grpcio installiert):
pip install grpcio-tools
Verwenden Sie den folgenden Befehl, um den Python-Boilerplate-Code zu generieren:
python -m grpc_tools.protoc --proto_path=./protos \
--python_out=. --pyi_out=. --grpc_python_out=. \
./protos/route_guide.proto
Dadurch werden die folgenden Dateien für die Schnittstellen generiert, die wir in route_guide.proto
definiert haben:
route_guide_pb2.py
enthält den Code, der dynamisch Klassen erstellt, die aus denmessage
-Definitionen generiert werden.route_guide_pb2.pyi
ist eine Stub-Datei oder „Type Hint“-Datei, die aus denmessage
-Definitionen generiert wird. Sie enthält nur die Signaturen ohne Implementierung. Stub-Dateien können von IDEs verwendet werden, um eine bessere automatische Vervollständigung und Fehlererkennung zu ermöglichen.route_guide_pb2_grpc.py
wird aus denservice
-Definitionen generiert und enthält gRPC-spezifische Klassen und Funktionen.
Der gRPC-spezifische Code enthält:
RouteGuideStub
, die von einem gRPC-Client zum Aufrufen von RouteGuide-RPCs verwendet werden kann.RouteGuideServicer
, das die Schnittstelle für Implementierungen desRouteGuide
-Dienstes definiert.- Die
add_RouteGuideServicer_to_server
-Funktion wird verwendet, um einenRouteGuideServicer
auf einem gRPC-Server zu registrieren.
5. Dienst erstellen
Sehen wir uns zuerst an, wie Sie einen RouteGuide
-Server erstellen. Das Erstellen und Ausführen eines RouteGuide
-Servers lässt sich in zwei Aufgaben unterteilen:
- Implementieren der Dienstschnittstelle, die aus unserer Dienstdefinition generiert wurde, mit Funktionen, die die eigentliche „Arbeit“ des Dienstes ausführen.
- Einen gRPC-Server an einem bestimmten Port ausführen, um auf Anfragen von Clients zu warten und Antworten zu übertragen.
Sie finden den ursprünglichen RouteGuide
-Server unter start_here/route_guide_server.py
.
RouteGuide implementieren
route_guide_server.py
hat eine RouteGuideServicer
-Klasse, die von der generierten Klasse route_guide_pb2_grpc.RouteGuideServicer
abgeleitet wird:
# RouteGuideServicer provides an implementation
# of the methods of the RouteGuide service.
class RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer):
RouteGuideServicer
implementiert alle RouteGuide
-Dienstmethoden.
Sehen wir uns eine einfache RPC-Implementierung genauer an. Die Methode GetFeature
ruft eine Point
vom Client ab und gibt die entsprechenden Featureinformationen aus ihrer Datenbank in Feature
zurück.
def GetFeature(self, request, context):
feature = get_feature(self.db, request)
if feature is None:
return route_guide_pb2.Feature(name="", location=request)
else:
return feature
Der Methode wird eine route_guide_pb2.Point
-Anfrage für den RPC und ein grpc.ServicerContext
-Objekt übergeben, das RPC-spezifische Informationen wie Zeitüberschreitungslimits enthält. Es wird eine route_guide_pb2.Feature
-Antwort zurückgegeben.
Server starten
Nachdem Sie alle RouteGuide
-Methoden implementiert haben, müssen Sie einen gRPC-Server starten, damit Clients Ihren Dienst verwenden können:
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
route_guide_pb2_grpc.add_RouteGuideServicer_to_server(
RouteGuideServicer(),
server,
)
listen_addr = "localhost:50051"
server.add_insecure_port(listen_addr)
print(f"Starting server on {listen_addr}")
server.start()
server.wait_for_termination()
Die Servermethode start()
ist nicht blockierend. Ein neuer Thread wird instanziiert, um Anfragen zu verarbeiten. Der Thread, der server.start()
aufruft, hat in der Zwischenzeit oft nichts anderes zu tun. In diesem Fall können Sie server.wait_for_termination()
aufrufen, um den aufrufenden Thread sauber zu blockieren, bis der Server beendet wird.
6. Client erstellen
In diesem Abschnitt sehen wir uns an, wie wir einen Client für unseren RouteGuide
-Dienst erstellen. Den ursprünglichen Clientcode finden Sie in start_here/route_guide_client.py
.
Stub erstellen
Um Dienstmethoden aufzurufen, müssen wir zuerst einen Stub erstellen.
Wir instanziieren die Klasse RouteGuideStub
des Moduls route_guide_pb2_grpc
, die aus unserem .proto
in der Datei route_guide_client.py
generiert wurde.
channel = grpc.insecure_channel("localhost:50051")
stub = route_guide_pb2_grpc.RouteGuideStub(channel)
Dienstmethoden aufrufen
Für RPC-Methoden, die eine einzelne Antwort zurückgeben (sogenannte response-unary-Methoden), unterstützt gRPC Python sowohl synchrone (blockierende) als auch asynchrone (nicht blockierende) Semantik für den Kontrollfluss.
Einfache RPC
Definieren wir zuerst eine Point
, mit der der Dienst aufgerufen werden kann. Dazu muss lediglich ein Objekt aus dem route_guide_pb2
-Paket mit einigen Properties instanziiert werden:
point = route_guide_pb2.Point(latitude=412346009, longitude=-744026814)
Ein synchroner Aufruf des einfachen RPC GetFeature
ist fast so einfach wie der Aufruf einer lokalen Methode. Der RPC-Aufruf wartet auf die Antwort des Servers und gibt entweder eine Antwort zurück oder löst eine Ausnahme aus. Wir können die Methode so aufrufen und die Antwort ansehen:
feature = stub.GetFeature(point)
print(feature)
Sie können die Felder des Feature-Objekts untersuchen und das Ergebnis der Anfrage ausgeben:
if feature.name:
print(f"Feature called '{feature.name}' at {format_point(feature.location)}")
else:
print(f"Found no feature at at {format_point(feature.location)}")
7. Jetzt ausprobieren
Führen Sie den Server aus:
python route_guide_server.py
Aktivieren Sie die virtuelle Umgebung in einem anderen Terminal noch einmal und führen Sie dann den Client aus:
python route_guide_client.py
Die Ausgabe sieht so aus (Zeitstempel wurden der Übersichtlichkeit halber weggelassen):
name: "16 Old Brook Lane, Warwick, NY 10990, USA" location { latitude: 412346009 longitude: -744026814 } Feature called '16 Old Brook Lane, Warwick, NY 10990, USA' at latitude: 412346009, longitude: -744026814
8. Nächste Schritte
- Informationen zur Funktionsweise von gRPC finden Sie unter Einführung in gRPC und Zentrale Konzepte.
- Grundlagen-Anleitung durcharbeiten
- Python API-Referenz