1. Introduzione
In questo codelab utilizzerai gRPC-Python per creare un client e un server che costituiscono la base di un'applicazione di mappatura di itinerari scritta in Python.
Al termine del tutorial, avrai un client che si connette a un server remoto utilizzando gRPC per ottenere il nome o l'indirizzo postale di ciò che si trova in coordinate specifiche su una mappa. Un'applicazione completa potrebbe utilizzare questa progettazione client-server per enumerare o riepilogare i punti di interesse lungo un percorso.
Il servizio è definito in un file Protocol Buffers, che verrà utilizzato per generare codice boilerplate per il client e il server in modo che possano comunicare tra loro, risparmiando tempo e fatica nell'implementazione di questa funzionalità.
Questo codice generato si occupa non solo delle complessità della comunicazione tra il server e il client, ma anche della serializzazione e della deserializzazione dei dati.
Obiettivi didattici
- Come utilizzare i buffer di protocollo per definire un'API di servizio.
- Come creare un client e un server basati su gRPC da una definizione di Protocol Buffers utilizzando la generazione automatica del codice.
- Comprensione della comunicazione client-server con gRPC.
Questo codelab è rivolto agli sviluppatori Python che non hanno mai utilizzato gRPC o che vogliono ripassare gRPC, nonché a chiunque sia interessato a creare sistemi distribuiti. Non è richiesta alcuna esperienza precedente con gRPC.
2. Prima di iniziare
Che cosa ti serve
- Python 3.9 o versioni successive. Ti consigliamo Python 3.13. Per istruzioni di installazione specifiche per la piattaforma, vedi Configurazione e utilizzo di Python. In alternativa, installa una versione di Python non di sistema utilizzando strumenti come uv o pyenv.
- pip per installare i pacchetti Python.
- venv per creare ambienti virtuali Python.
I pacchetti ensurepip
e venv
fanno parte della libreria standard di Python e sono in genere disponibili per impostazione predefinita.
Tuttavia, alcune distribuzioni basate su Debian (inclusa Ubuntu) scelgono di escluderli durante la ridistribuzione di Python. Per installare i pacchetti, esegui:
sudo apt install python3-pip python3-venv
Ottieni il codice
Per semplificare l'apprendimento, questo codelab offre uno scaffold di codice sorgente predefinito per aiutarti a iniziare. I passaggi seguenti ti guideranno nel completamento dell'applicazione, inclusa la generazione di codice gRPC utilizzando il plug-in del compilatore del buffer di protocollo grpc_tools.protoc
.
grpc-codelabs
Il codice sorgente dello scaffold per questo codelab è disponibile nella directory codelabs/grpc-python-getting-started/start_here. Se preferisci non implementare il codice autonomamente, il codice sorgente completato è disponibile nella directory completed
.
Innanzitutto, crea la directory di lavoro del codelab e accedi tramite cd:
mkdir grpc-python-getting-started && cd grpc-python-getting-started
Scarica ed estrai il codelab:
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
In alternativa, puoi scaricare il file .zip contenente solo la directory del codelab e decomprimerlo manualmente.
3. Definisci il servizio
Il primo passo consiste nel definire il servizio gRPC dell'applicazione, il relativo metodo RPC e i tipi di messaggi di richiesta e risposta utilizzando il linguaggio di definizione dell'interfaccia Protocol Buffers. Il tuo servizio fornirà:
- Un metodo RPC chiamato
GetFeature
che il server implementa e il client chiama. - I tipi di messaggio
Point
eFeature
sono strutture di dati scambiate tra il client e il server quando si utilizza il metodoGetFeature
. Il client fornisce le coordinate della mappa comePoint
nella richiestaGetFeature
al server e il server risponde con unFeature
corrispondente che descrive ciò che si trova a quelle coordinate.
Questo metodo RPC e i relativi tipi di messaggio verranno definiti nel file protos/route_guide.proto
del codice sorgente fornito.
Protocol Buffers è comunemente noto come protobuf. Per ulteriori informazioni sulla terminologia gRPC, consulta Concetti fondamentali, architettura e ciclo di vita di gRPC.
Tipi di messaggi
Nel file protos/route_guide.proto
del codice sorgente, definisci innanzitutto il tipo di messaggio Point
. Un Point
rappresenta una coppia di coordinate di latitudine e longitudine su una mappa. Per questo codelab, utilizza numeri interi per le coordinate:
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
I numeri 1
e 2
sono numeri ID univoci per ciascuno dei campi nella struttura message
.
Successivamente, definisci il tipo di messaggio Feature
. Un Feature
utilizza un campo string
per il nome o l'indirizzo postale di un elemento in una località specificata da un Point
:
message Feature {
// The name or address of the feature.
string name = 1;
// The point where the feature is located.
Point location = 2;
}
Metodo di servizio
Il file route_guide.proto
ha una struttura service
denominata RouteGuide
che definisce uno o più metodi forniti dal servizio dell'applicazione.
Aggiungi il metodo rpc
GetFeature
all'interno della definizione di RouteGuide
. Come spiegato in precedenza, questo metodo cerca il nome o l'indirizzo di una località da un determinato insieme di coordinate, quindi GetFeature
restituisce un Feature
per un determinato Point
:
service RouteGuide {
// Definition of the service goes here
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
}
Si tratta di un metodo RPC unario: una RPC semplice in cui il client invia una richiesta al server e attende una risposta, proprio come una chiamata di funzione locale.
4. Genera il codice client e server
A questo punto, genera il codice gRPC boilerplate sia per il client che per il server dal file .proto
utilizzando il compilatore del buffer del protocollo.
Per la generazione di codice Python gRPC, abbiamo creato grpcio-tools. Comprende:
- Il compilatore protoc standard che genera codice Python dalle definizioni
message
. - Plug-in protobuf gRPC che genera codice Python (stub client e server) dalle definizioni
service
.
Installeremo il pacchetto Python grpcio-tools
utilizzando pip. Creiamo un nuovo ambiente virtuale Python (venv) per isolare le dipendenze del progetto dai pacchetti di sistema:
python3 -m venv --upgrade-deps .venv
Per attivare l'ambiente virtuale nella shell bash/zsh:
source .venv/bin/activate
Per Windows e shell non standard, consulta la tabella all'indirizzo https://docs.python.org/3/library/venv.html#how-venvs-work.
Poi, installa grpcio-tools (in questo modo viene installato anche il pacchetto grpcio):
pip install grpcio-tools
Utilizza il seguente comando per generare il codice boilerplate Python:
python -m grpc_tools.protoc --proto_path=./protos \
--python_out=. --pyi_out=. --grpc_python_out=. \
./protos/route_guide.proto
Verranno generati i seguenti file per le interfacce definite in route_guide.proto
:
route_guide_pb2.py
contiene il codice che crea dinamicamente le classi generate dalle definizioni dimessage
.route_guide_pb2.pyi
è un "file stub" o "file di suggerimenti sul tipo" generato dalle definizionimessage
. Contiene solo le firme senza implementazione. I file stub possono essere utilizzati dagli IDE per fornire un completamento automatico e un rilevamento degli errori migliori.route_guide_pb2_grpc.py
viene generato dalle definizioni diservice
e contiene classi e funzioni specifiche di gRPC.
Il codice specifico di gRPC contiene:
RouteGuideStub
, che può essere utilizzato da un client gRPC per richiamare RPC RouteGuide.RouteGuideServicer
, che definisce l'interfaccia per le implementazioni del servizioRouteGuide
.add_RouteGuideServicer_to_server
, che viene utilizzata per registrare unRouteGuideServicer
in un server gRPC.
5. Crea il servizio
Per prima cosa, vediamo come creare un server RouteGuide
. La creazione e l'esecuzione di un server RouteGuide
si suddivide in due elementi di lavoro:
- Implementazione dell'interfaccia del servizio generata dalla nostra definizione del servizio con funzioni che eseguono il "lavoro" effettivo del servizio.
- Esecuzione di un server gRPC su una porta specifica per ascoltare le richieste dei client e trasmettere le risposte.
Puoi trovare il server RouteGuide
iniziale in start_here/route_guide_server.py
.
Implementa RouteGuide
route_guide_server.py
ha una classe RouteGuideServicer
che crea sottoclassi della classe generata route_guide_pb2_grpc.RouteGuideServicer
:
# RouteGuideServicer provides an implementation
# of the methods of the RouteGuide service.
class RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer):
RouteGuideServicer
implementa tutti i metodi di servizio RouteGuide
.
Esaminiamo in dettaglio una semplice implementazione RPC. Il metodo GetFeature
riceve un Point
dal client e restituisce le informazioni sulla funzionalità corrispondenti dal suo database in Feature
.
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
Al metodo viene passata una richiesta route_guide_pb2.Point
per la RPC e un oggetto grpc.ServicerContext
che fornisce informazioni specifiche della RPC, come i limiti di timeout. Restituisce una risposta route_guide_pb2.Feature
.
Avvio del server
Dopo aver implementato tutti i metodi RouteGuide
, il passaggio successivo consiste nell'avviare un server gRPC in modo che i client possano effettivamente utilizzare il tuo servizio:
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()
Il metodo start()
del server non è bloccante. Verrà creata una nuova istanza di thread per gestire le richieste. Il thread che chiama server.start()
spesso non avrà altro lavoro da fare nel frattempo. In questo caso, puoi chiamare server.wait_for_termination()
per bloccare in modo pulito il thread di chiamata finché il server non termina.
6. Crea il client
In questa sezione vedremo come creare un client per il nostro servizio RouteGuide
. Puoi visualizzare il codice cliente iniziale in start_here/route_guide_client.py
.
Creare uno stub
Per chiamare i metodi di servizio, dobbiamo prima creare uno stub.
Istanziamo la classe RouteGuideStub
del modulo route_guide_pb2_grpc
, generata dal nostro .proto
all'interno del file route_guide_client.py
.
channel = grpc.insecure_channel("localhost:50051")
stub = route_guide_pb2_grpc.RouteGuideStub(channel)
Metodi di servizio di chiamata
Per i metodi RPC che restituiscono una singola risposta, noti come metodi response-unary, gRPC Python supporta la semantica del flusso di controllo sincrono (bloccante) e asincrono (non bloccante).
RPC semplice
Innanzitutto, definiamo un Point
per chiamare il servizio. L'operazione dovrebbe essere semplice come l'istanza di un oggetto dal pacchetto route_guide_pb2
con alcune proprietà:
point = route_guide_pb2.Point(latitude=412346009, longitude=-744026814)
Una chiamata sincrona alla semplice RPC GetFeature
è quasi semplice come chiamare un metodo locale. La chiamata RPC attende la risposta del server e restituisce una risposta o genera un'eccezione. Possiamo chiamare il metodo e visualizzare la risposta in questo modo:
feature = stub.GetFeature(point)
print(feature)
Puoi esaminare i campi dell'oggetto Feature e restituire l'output della richiesta:
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. Prova
Esegui il server:
python route_guide_server.py
Da un altro terminale, attiva di nuovo l'ambiente virtuale, quindi esegui il client:
python route_guide_client.py
Vedrai un output simile a questo, con i timestamp omessi per chiarezza:
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. Passaggi successivi
- Scopri come funziona gRPC in Introduzione a gRPC e Concetti di base.
- Completa il tutorial sulle nozioni di base.
- Esplora il riferimento API Python.