In diesem Artikel erörtern wir, wie Sie einen einfachen gRPC-API-Dienst für einen Endpunkt mit Protokollpuffern erstellen und seinen clientseitigen und serverseitigen Code mit gRPC-Tools vorbereiten. Dies wird ein Versuch sein, von vorne zu beginnen, eine einfache Funktion zu nehmen und sie über eine gRPC-Schnittstelle auf unserem eigenen Computer verfügbar zu machen. Wir werden gRPC nicht in erweiterten Modi (Request-Streaming, Response-Streaming, bidirektionales Streaming) mit zusätzlichen Funktionen wie Fehlerbehandlung und Authentifizierung verwenden. Dieses Tutorial hilft Ihnen beim Erstellen von APIs mit gRPC in Python.

Was ist gRPC?

gRPC oder Google Remote Procedure Call ist ein Open-Source-RPC-Framework, das auf Schnelligkeit und Effizienz ausgelegt ist. Es wurde von Google mit dem Ziel erstellt, ein modernes RPC-Framework zu entwickeln, das in jeder Umgebung ausgeführt werden kann. Sie wollten etwas, das überall laufen kann, auch in beiden Rechenzentren oder auf der letzten Meile des verteilten Computing, um Geräte, mobile Anwendungen und Browser mit Backend-Diensten zu verbinden. Es ist ein modernes, hochleistungsfähiges Open-Source-RPC-Framework.

Was es von herkömmlichen REST-APIs unterscheidet, ist, dass es auf Protokollpuffer angewiesen ist, um sowohl die Datenstrukturen als auch die Serialisierungsformate zu definieren. gRPC ist mit mehreren Programmiersprachen kompatibel und unterstützt Lastenausgleich, Ablaufverfolgung, Zustandsprüfung und Authentifizierung. Es enthält auch eine Pluggable-Unterstützung für die sprachübergreifende Diensterkennung.

Erstellen einer anzuzeigenden Funktion

Lassen Sie uns zunächst eine Funktion (Prozedur) erstellen, die wir verfügbar machen und aus der Ferne aufrufen . Wir können diese Datei in einem Ordner mit dem Namen grpc-tutorial-python erstellen und lokalisieren.

#calculator.py
import math

def square_root(x):
  y = math.sqrt(x)
  return y

Hier haben wir gerade eine grundlegende Funktion mit der Mathematikbibliothek erstellt, um die Quadratwurzel von x auszugeben. Es ist nur zum Testen, Sie können hier alles eingeben, was Sie wollen, sogar eine einfache Druckfunktion wird ausreichen.

Generieren der gRPC-Klassen

Hier werden wir den gRPC-Dienst mit der von Protocol Buffers generierten Sprache erstellen. Protokollpuffer werden verwendet, um Nachrichten, ihre Datentypen und die Dienstmodelle in einer Proto-Datei zu definieren. Die Proto-Datei ist eine Textdatei, die mit der Erweiterung .proto endet und mit der Syntax des Protokollpuffers geschrieben wurde. Wir können dies in einem separaten Ordner, cal, machen, um Ordnung zu halten.

#calculator.proto
syntax = "proto3";

message Number {
    float value = 1;
}

service Calculator {
    rpc SquareRoot(Number) returns (Number) {}
}

Das Dienstmodell ist im Grunde die Definition, wie unsere Dienste Daten übertragen und miteinander interagieren. Dann generieren wir mithilfe der protoc-Kompilierung Code für die Nachrichten- und Serverklassen.

Nachdem das Dienstmodell in der .proto-Datei definiert wurde, können wir die Dienstdateien generieren, indem wir den protoc-Befehl für die .proto-Datei ausführen. Der Befehl protoc generiert automatisch Code für die neuen Dateien (und Klassen). Dazu benötigen wir einige gRPC-Bibliotheken oder -Tools, die mit den folgenden Befehlen installiert werden können:

pip install grpcio
pip install grpcio-tools

Danach können wir den protoc-Befehl für die .proto-Datei ausführen, indem wir den folgenden Befehl ausführen:

python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. cal/calculator.proto

Wenn alles richtig funktioniert hat, werden die beiden folgenden Dateien erstellt:

cal/calculator_pb2.py --which  contains message classes
cal/calculator_pb2_grpc.py -- which contains server and client classes

Erstellen eines gRPC-Servers

Nachdem wir alle Dateien generiert haben, die wir zum Erstellen des Servers benötigt haben, können wir endlich mit dem Schreiben der Serverdatei beginnen:

import grpc
from concurrent import futures
import time

#import the generated files
import cal.calculator_pb2 as calculator_pb2
import cal.calculator_pb2_grpc as calculator_pb2_grpc

#import the function files
import calculator

#create a class to define the server functions derived from calculator_pb2_grpc (or the server and client classes)
class CalculatorServicer(calculator_pb2_grpc.CalculatorServicer):

    #calculator.square_root is exposed here
    def SquareRoot(self, request, context):
        response = calculator_pb2.Number()
        response.value = calculator.square_root(request.value)
        return response


#create a gRPC server
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))

#use the function "add_CalculatorServicer_to_server" to add the defined class to the created server
calculator_pb2_grpc.add_CalculatorServicer_to_server(
        CalculatorServicer(), server)

#listen on port 50051
print('Starting server. Listening on port 8000.')
server.add_insecure_port('[::]:8000')
server.start()

# since server.start() will not block be blocked ever, a sleep-loop is added to keep alive
try:
    while True:
        time.sleep(86400)
except KeyboardInterrupt:
    server.stop(0)

gRPC ruft die überschriebene square_root-Methode in der CalculatorServicer-Klasse automatisch auf, wenn ein Client auf den SquareRoot-Endpunkt zugreift. Wir können jetzt auch den Server starten, um zu sehen, ob alles funktioniert oder nicht, was möglich ist mit:

python server.py

Und wenn Sie eine Antwort wie diese erhalten, bedeutet das, dass Ihr Code funktioniert hat:

Jetzt haben wir einen Live-gRPC-Server, der auf Port 8000 läuft und Ereignisse auflistet.

Verwenden Sie als Nächstes CalculatorStub, um einen Client für den gRPC-API-Dienst zu erstellen, wie unten gezeigt:

import grpc

#import the generated files
import cal.calculator_pb2 as calculator_pb2
import cal.calculator_pb2_grpc as calculator_pb2_grpc

#open and connect to the gRPC channel we just created
channel = grpc.insecure_channel('localhost:8000')

#create a stub (client)
stub = calculator_pb2_grpc.CalculatorStub(channel)

#create a valid request message or just any number in our case
number = calculator_pb2.Number(value=15)

#make the call
response = stub.SquareRoot(number)

#print the results
print(response.value)

Der Client stellt eine Verbindung zu einer API her, die Sie über GRPC anbieten. Ihr Server verwendet die CalculatorService-Klasse mit einem Namensparameter, um eine Instanz davon zu erwerben. gRPC interpretiert diese Python-Klasse als eine von Protocol Buffers definierte. Anschließend erstellt es eine Instanz von Python, indem es die CalculatorService Protobuf-Nachricht analysiert und über eine GRPC-Verbindung an Ihren Server weiterleitet. Die Antwort Ihres Servers, eine User Protocol Buffers-Nachricht, wird dann in eine User-Python-Klasse geparst und dann ausgedruckt.

Stellen Sie sich die .proto-Datei als einen Vertrag zwischen dem Server und seinen Clients vor. gRPC ist der Kurier und Protocol Buffers ist der Schlichter/Übersetzer, der den Vertrag durchsetzt. Protocol Buffers übersetzen das, was Clients und Server sprechen, aus/in eine universelle Übersetzersprache, wobei gRPC die Kommunikation in HTTP/2 herumträgt. Wenn Sie mit Protocol Buffers und gRPC arbeiten, können Sie sich mehr auf die wahre Funktionalität Ihrer Anwendung konzentrieren.

Results

python3 client.py

Wir können diese Datei ähnlich wie bei der anderen ausführen:

Beachten Sie, dass wir die Serverdatei laufen lassen müssen, wenn wir dies ausführen, da sich dort unsere API befindet. Sie können dafür ein anderes Terminal öffnen.

Nachdem Sie die obige Datei ausgeführt haben, sollten Sie eine ähnliche Antwort wie diese erhalten:

Das heißt es hat funktioniert!!

der Abschluss

Die Microservice-Architektur ist derzeit in aller Munde. Mit Microservices können Sie Ihre monolithische Architektur in viele kleinere Services aufteilen, die jeweils über eine eigene Codebasis, einen eigenen Datenspeicher und eine bereitstellbare Instanz verfügen und über ein Netzwerk miteinander kommunizieren. Es gibt andere Feinheiten, die gRPC ausmachen, wie z. B. Response-Streaming und bidirektionales Streaming, aber ich hoffe, dass dieser Beitrag eine gute Referenz für diejenigen wird, die gerade erst anfangen.

Bei diesem Projekt gibt es viel Raum für Verbesserungen, also versuchen Sie es selbst und experimentieren Sie mit Hilfe der Google-Dokumentation zu gRPC. So erstellen Sie also APIs mit gRPC in Python.