Cloud Endpoints supporta la transcodifica del protocollo in modo che i client possano accedere alla tua API gRPC utilizzando HTTP/JSON. Il proxy di servizio Extensible (ESP) transcodisce HTTP/JSON in gRPC.
Questa guida descrive:
- Come utilizzare le annotazioni nel file
.proto
per specificare la conversione dei dati da HTTP/JSON a gRPC - Come eseguire il deployment del servizio in Endpoints per utilizzare questa funzionalità
- Dove trovare ulteriori informazioni di riferimento sulla progettazione e sull'implementazione del transcoding per i servizi gRPC
Si presume che tu abbia già completato i nostri tutorial su gRPC e che tu abbia familiarità con i concetti di base degli endpoint per le API gRPC.
Progettare un'API adatta alla transcodifica
La transcodifica prevede la mappatura delle richieste HTTP/JSON e dei relativi parametri ai metodi gRPC e ai loro parametri e tipi di ritorno. Per questo motivo, anche se è possibile mappare una richiesta HTTP/JSON a qualsiasi metodo API arbitrario, è consigliabile farlo se l'API gRPC è strutturata in modo orientato alle risorse, proprio come un'API HTTP
REST tradizionale. In altre parole, progetti il servizio API in modo che utilizzi un numero ridotto di metodi standard, corrispondenti a verbi HTTP come GET
e PUT
, che operano sulle risorse e sulle raccolte di risorse del servizio, che sono esse stesse un tipo di risorsa. Questi metodi standard sono List
,
Get
, Create
, Update
e Delete
.
Se necessario, l'API può avere anche alcuni metodi personalizzati non standard, anche se la loro mappatura non è così semplice.
Puoi scoprire di più sul design orientato alle risorse e sulle mappature di transcodifica standard nella guida alla progettazione delle API. Questa guida alla progettazione è lo standard di progettazione seguito in Google per la progettazione di API pubbliche come le API Cloud. Sebbene non sia necessario seguire questa guida per utilizzare la transcodifica gRPC, ti consigliamo vivamente di farlo. In particolare, le seguenti pagine possono aiutarti a comprendere questi principi di progettazione e ad aggiungere mappature di transcodifica utili ai tuoi metodi:
- Progettazione orientata alle risorse
- Metodi standard
- Metodi personalizzati
- Verbi HTTP: questa pagina fornisce linee guida aggiuntive per le implementazioni dei metodi se si prevede di accedervi tramite HTTP.
Potrebbe essere utile anche la seguente pagina di riferimento:
- Riferimento alle regole HTTP: un riferimento completo per le regole di mappatura HTTP,
Nel resto di questo documento, utilizzerai l'esempio della libreria che hai utilizzato nei nostri
tutorial, che già utilizza questi principi.
La Libreria contiene raccolte di risorse "libri", che gli utenti possono
List
, Get
, Create
o Delete
.
Dove configurare la transcodifica
La transcodifica gRPC è abilitata per impostazione predefinita e puoi utilizzarla senza alcuna configurazione. Segui le istruzioni per implementare un servizio che utilizza la transcodifica.
Successivamente, quando invii una richiesta POST
HTTP al percorso dell'URL
GRPC_SERVICE_FULL_NAME/METHOD_NAME>
con i valori dei campi del messaggio di richiesta del metodo (se presenti) come JSON nel corpo della richiesta HTTP,
l'ESP invia il messaggio di richiesta al metodo gRPC appropriato. Nell'esempio precedente,
GRPC_SERVICE_FULL_NAME
è il nome completo del servizio gRPC
e METHOD_NAME
è il nome del metodo.
Ad esempio, se invii un POST
all'URL ListShelves
della libreria come segue:
curl -XPOST http://mydomain/endpoints.examples.bookstore.Bookstore/ListShelves
Riceverai un elenco aggiornato delle sezioni in formato JSON.
Tuttavia, in termini di progettazione dell'interfaccia HTTP, è fortemente preferibile configurare esplicitamente le mappature, come descritto nel resto di questo documento.
Lo standard di configurazione dell'API gRPC per la configurazione del servizio ti consente di specificare esattamente come devono essere tradotti i dati da HTTP/JSON a gRPC. Per farlo sono supportati due meccanismi: annotazioni dirette nel file .proto
e in YAML nell'ambito del file di configurazione dell'API gRPC. Ti consigliamo di utilizzare le annotazioni proto
per facilitare la lettura e la manutenzione.
Per ulteriori informazioni sulla configurazione YAML e su quando potrebbe essere necessario utilizzarla, consulta Configurare la transcodifica in YAML.
Ecco un esempio che utilizza l'approccio consigliato dalla libreria:
// Returns a specific bookstore shelf.
rpc GetShelf(GetShelfRequest) returns (Shelf) {
// Client example - returns the first shelf:
// curl http://DOMAIN_NAME/v1/shelves/1
option (google.api.http) = { get: "/v1/shelves/{shelf}" };
}
...
// Request message for GetShelf method.
message GetShelfRequest {
// The ID of the shelf resource to retrieve.
int64 shelf = 1;
}
L'annotazione indica all'ESP che l'invio di una richiesta HTTP GET
con l'URL http://mydomain/v1/shelves/1
chiama il metodo GetShelf()
del server gRPC, con un GetShelfRequest
contenente l'ID sezione richiesto shelf
(in questo caso 1
).
Aggiunta di mappature di transcodifica
Questa sezione descrive alcune annotazioni di mappatura aggiuntive dell'esempio Libreria. Nell'esempio di Bookstore sono presenti due file proto
di esempio, in modo da poterli implementare sia con che senza le mappature di transcodifica e confrontare le differenze nei file proto
:
bookstore.proto
: viene utilizzato nei tutorial di Endpoints e non ha mappature di transcoding.http_bookstore.proto
: sono state aggiunte associazioni di transcodifica.
Per una guida più completa su come specificare le mappature di transcodifica, consulta Metodi standard, Metodi personalizzati e il riferimento alle regole HTTP.
Mappare un metodo List
Il metodo List
è definito nel file .proto
con il relativo tipo di risposta:
// Returns a list of all shelves in the bookstore. rpc ListShelves(google.protobuf.Empty) returns (ListShelvesResponse) { // Define HTTP mapping. // Client example (Assuming your service is hosted at the given 'DOMAIN_NAME'): // curl http://DOMAIN_NAME/v1/shelves option (google.api.http) = { get: "/v1/shelves" }; } ... message ListShelvesResponse { // Shelves in the bookstore. repeated Shelf shelves = 1; }
L'annotazione in grassetto specifica la mappatura HTTP per questo metodo.
option (google.api.http)
specifica che questo metodo è un'annotazione di mappatura HTTP gRPC.get
specifica che questo metodo è mappato a una richiestaGET
HTTP."/v1/shelves"
è il modello di percorso dell'URL (aggiunto al dominio del servizio) utilizzato dalla richiestaGET
per chiamare questo metodo. Il percorso dell'URL è noto anche come percorso della risorsa perché in genere specifica la "cosa" o la risorsa che vuoi utilizzare. In questo caso, tutte le risorse della sezione del nostro Negozio di libri.
Ad esempio, se un client chiama questo metodo inviando un GET
all'URL
http://mydomain/v1/shelves
, ESP chiama il metodo gRPC
ListShelves()
. Il backend gRPC restituisce quindi le sezioni, che
ESP converte in formato JSON e restituisce al client.
Mappare un metodo Get
Il metodo GetShelf
della libreria è definito nel file .proto
con i relativi tipi di richiesta e risposta:
// Returns a specific bookstore shelf. rpc GetShelf(GetShelfRequest) returns (Shelf) { // Client example - returns the first shelf: // curl http://DOMAIN_NAME/v1/shelves/1 option (google.api.http) = { get: "/v1/shelves/{shelf}" }; } ... // Request message for GetShelf method. message GetShelfRequest { // The ID of the shelf resource to retrieve. int64 shelf = 1; } ... // A shelf resource. message Shelf { // A unique shelf id. int64 id = 1; // A theme of the shelf (fiction, poetry, etc). string theme = 2; }
L'annotazione in grassetto specifica la mappatura HTTP per questo metodo.
option (google.api.http)
specifica che questo metodo è un'annotazione di mappatura HTTP gRPC.get
specifica che questo metodo è mappato a una richiesta HTTPGET
."/v1/shelves/{shelf}"
è il percorso dell'URL per la richiesta, come prima, ma specifica/v1/shelves/
e poi{shelf}
. Questa notazione con parentesi graffe indica a ESP che qualsiasi valore in{shelf}
è il valore da fornire pershelf
nel parametroGetShelfRequest
del metodo.
Se un client chiama questo metodo inviando un GET
all'URL
http://mydomain/v1/shelves/4
, ESP crea un
GetShelfRequest
con un valore shelf
pari a 4
e poi chiama il metodo gRPC
GetShelf()
con questo valore. Il backend gRPC restituisce quindi il Shelf
richiesto con
l'ID 4
, che ESP converte in formato JSON e restituisce al
client.
Questo metodo richiede solo che il client fornisca un singolo valore del campo della richiesta, shelf
, che specifichi nel modello di percorso dell'URL con la notazione "acquisizione" tra parentesi graffe. Se necessario, puoi acquisire più parti dell'URL per identificare la risorsa richiesta. Ad esempio, il metodo GetBook
richiede al client di specificare sia l'ID sezione sia l'ID libro nell'URL:
// Returns a specific book.
rpc GetBook(GetBookRequest) returns (Book) {
// Client example - get the first book from the second shelf:
// curl http://DOMAIN_NAME/v1/shelves/2/books/1
option (google.api.http) = { get: "/v1/shelves/{shelf}/books/{book}" };
}
...
// Request message for GetBook method.
message GetBookRequest {
// The ID of the shelf from which to retrieve a book.
int64 shelf = 1;
// The ID of the book to retrieve.
int64 book = 2;
}
Oltre ai valori letterali e alle parentesi graffe di acquisizione per i valori di campo, i modelli di percorso dell'URL possono utilizzare caratteri jolly per indicare che qualsiasi elemento in questa parte dell'URL deve essere acquisito. La notazione {shelf}
utilizzata nell'esempio precedente è in realtà una scorciatoia per {shelf=*}
. Puoi scoprire di più sulle regole per i modelli di percorso nel riferimento alle regole HTTP.
Per questo tipo di metodo, non è specificato il corpo della richiesta HTTP. Puoi trovare altre linee guida per la mappatura dei metodi Get
, incluso l'utilizzo parametri di ricerca, in Metodi standard.
Mappare un metodo Create
Il metodo CreateShelf
della libreria corrisponde a POST
HTTP.
// Creates a new shelf in the bookstore. rpc CreateShelf(CreateShelfRequest) returns (Shelf) { // Client example: // curl -d '{"theme":"Music"}' http://DOMAIN_NAME/v1/shelves option (google.api.http) = { post: "/v1/shelves" body: "shelf" }; } ... // Request message for CreateShelf method. message CreateShelfRequest { // The shelf resource to create. Shelf shelf = 1; } ... // A shelf resource. message Shelf { // A unique shelf id. int64 id = 1; // A theme of the shelf (fiction, poetry, etc). string theme = 2; }
option (google.api.http)
specifica che questo metodo è un'annotazione di mappatura HTTP gRPC.post
specifica che questo metodo è mappato a una richiesta HTTPPOST
."/v1/shelves"
è il percorso dell'URL per la richiesta, come prima.body: "shelf"
viene utilizzato nel corpo della richiesta HTTP per specificare la risorsa da aggiungere in formato JSON.
Ad esempio, se un client chiama questo metodo come segue:
curl -d '{"theme":"Music"}' http://DOMAIN_NAME/v1/shelves
ESP utilizza il corpo JSON per creare un valore Shelf
con il tema
"Music"
per CreateShelfRequest
e poi chiama il metodo gRPC CreateShelf()
. Tieni presente che il client non fornisce il valore id
per Shelf
.
Gli ID sezione della libreria vengono forniti dal servizio quando viene creata una nuova sezione.
Fornisci questo tipo di informazioni agli utenti del tuo servizio nella documentazione dell'API.
Utilizzare un carattere jolly nel corpo
Il nome speciale *
può essere utilizzato nella mappatura del corpo per indicare che ogni campo non vincolato dal modello di percorso deve essere mappato al corpo della richiesta.
In questo modo viene attivata la seguente definizione alternativa del metodo CreateShelf
.
// Creates a new shelf in the bookstore. rpc CreateShelf(CreateShelfRequest) returns (Shelf) { // Client example: // curl -d '{"shelf_theme":"Music", "shelf_size": 20}' http://DOMAIN_NAME/v1/shelves/123 option (google.api.http) = { post: "/v1/shelves/{shelf_id}" body: "*" }; } ... // Request message for CreateShelf method. message CreateShelfRequest { // A unique shelf id. int64 shelf_id = 1; // A theme of the shelf (fiction, poetry, etc). string shelf_theme = 2; // The size of the shelf int64 shelf_size = 3; }
option (google.api.http)
specifica che questo metodo è un'annotazione di mappatura HTTP gRPC.post
specifica che questo metodo è mappato a una richiestaPOST
HTTP."/v1/shelves/{shelf_id}"
è il percorso dell'URL per la richiesta. Qualsiasi valore in{shelf_id}
è il valore del camposhelf_id
inCreateShelfRequest
.body: "*"
viene utilizzato nel corpo della richiesta HTTP per specificare tutti i campi della richiesta rimanenti, ad eccezione dishelf_id
in questo esempio, ovveroshelf_theme
eshelf_size
. Per tutti i campi del corpo JSON con questi due nomi, i relativi valori verranno utilizzati nei campi corrispondenti diCreateShelfRequest
.
Ad esempio, se un client chiama questo metodo nel seguente modo:
curl -d '{"shelf_theme":"Music", "shelf_size": 20}' http://DOMAIN_NAME/v1/shelves/123
ESP utilizza il corpo JSON e il modello di percorso per creare un CreateShelfRequest{shelf_id: 123 shelf_theme: "Music" shelf_size: 20}
,
quindi lo utilizza per chiamare il metodo gRPC CreateShelf()
. Per maggiori dettagli, consulta HttpRule.
Configurazione della transcodifica in YAML
Un approccio alternativo consiste nello specificare le mappature da HTTP a gRPC nel file YAML di configurazione dell'API gRPC anziché nel file .proto
. Potresti dover configurare la transcodifica in un file YAML se hai una singola definizione dell'API proto
utilizzata in più servizi, con mappature diverse specificate per ciascun servizio.
rules
nella sezione http
del file YAML specifica come mappare le richieste HTTP/JSON ai metodi gRPC:
http:
rules:
...
#
# 'GetShelf' is available via the GET HTTP verb and '/shelves/{shelf}' URL
# path, where {shelf} is the value of the 'shelf' field of 'GetShelfRequest'
# protobuf message.
#
# Client example - returns the first shelf:
# curl http://DOMAIN_NAME/v1/shelves/1
#
- selector: endpoints.examples.bookstore.Bookstore.GetShelf
get: /v1/shelves/{shelf}
...
Un esempio più completo dell'utilizzo di questo approccio per il servizio di esempio Libreria si trova in api_config_http.yaml
.
Eseguire il deployment di un servizio che utilizza la transcodifica
Il deployment di un servizio gRPC che utilizza la transcodifica è molto simile a quello di qualsiasi altro servizio gRPC, con una differenza sostanziale. Nei
tutorial, l'esempio doveva accettare le richieste gRPC
del client di esempio. Tuttavia, se vuoi che la libreria accetti anche le richieste HTTP, devi eseguire un'ulteriore configurazione per ESP. I client utilizzano il protocollo HTTP1.1
per inviare richieste JSON/HTTP all'ESP, pertanto l'ESP deve essere configurato per utilizzare SSL (la porta SSL può supportare entrambi i tipi di richiesta) o deve avere una porta speciale abilitata per accettare queste chiamate. Per il resto, il deployment è molto simile a quello descritto nel tutorial per l'ambiente scelto.
Assicurati che le regole HTTP siano dipistate
Se hai già scaricato l'esempio della libreria per i
tutorial, tieni presente che devi scaricare una
versione leggermente diversa del file .proto
con le annotazioni,
http_bookstore.proto
.
Inoltre, devi clonare il repository
googleapis
da GitHub
prima di eseguire protoc
, poiché hai bisogno di
annotations.proto
nel percorso di inclusione.
git clone https://github.com/googleapis/googleapis
GOOGLEAPIS_DIR=<your-local-googleapis-folder>
Poi, crea un nuovo descrittore .pb
da http_bookstore.proto
durante il deployment della configurazione in Endpoints:
protoc \
--include_imports \
--include_source_info \
--proto_path=${GOOGLEAPIS_DIR} \
--proto_path=. \
--descriptor_set_out=api_descriptor.pb \
http_bookstore.proto
Se utilizzi il metodo alternativo per configurare le mappature HTTP nel file YAML della configurazione dell'API gRPC, devi anche assicurarti che le regole pertinenti vengano implementate durante il deployment della configurazione in Endpoints. Per provare questa operazione con il servizio Libreria, le relative regole di base si trovano nel file api_config.yaml
e le regole HTTP nel file api_config_http.yaml
:
gcloud endpoints services deploy api_descriptor.pb api_config.yaml api_config_http.yaml
Utilizzo di SSL
Se SSL è abilitato per la comunicazione tra i client e l'ESP,
i client possono utilizzare la stessa porta per effettuare chiamate gRPC o HTTP1.1
. Puoi scoprire come configurare SSL per un servizio Endpoints in Abilitazione di SSL.
Specifica una porta per consentire a ESP di accettare le chiamate SSL utilizzando il flag --ssl_port
nel file di configurazione di Google Kubernetes Engine (GKE) o il comando docker run
(Compute Engine/Docker).
args: [
"--http_port", "8080",
"--ssl_port", "443", # enable SSL port at 443 to serve https requests
"--backend", "grpc://127.0.0.1:8081", # gRPC backend.
"--service", "SERVICE_NAME",
"--rollout_strategy", "managed",
]
Configurazione di una porta HTTP1.1
Se non utilizzi SSL, devi configurare una porta separata per le richieste HTTP1.1
perché gRPC e HTTP1.1
non possono condividere la stessa porta senza SSL. Utilizza
il flag --http_port
nel file di configurazione GKE o
il comando docker run
per specificare una porta per
accettare le chiamate HTTP1.1
. Se vuoi anche che l'ESP accetti le chiamate gRPC, devi utilizzare anche il flag --http2_port
per specificare una porta gRPC.
args: [
"--http_port", "8080", # for HTTP 1.1
"--http2_port", "8090", # for gRPC
"--backend", "grpc://127.0.0.1:8081", # gRPC backend.
"--service", "SERVICE_NAME",
"--rollout_strategy", "managed",
]
Chiamare un servizio utilizzando la transcodifica
Questa sezione descrive la configurazione del servizio e come effettuare chiamate HTTP al servizio.
Configurazione del servizio
Si presume che tu abbia già completato i tutorial di base sul servizio gRPC per l'ambiente scelto e che tu abbia un cluster GKE o un'istanza Compute Engine per eseguire l'esempio.
- Innanzitutto, assicurati di aver eseguito il deployment della configurazione del servizio Bookstore abilitato per HTTP in Endpoints, come descritto in Verificare il deployment delle regole HTTP.
Esegui il deployment del backend e dell'ESP come descritto nel tutorial per la piattaforma scelta, utilizzando il flag
--http_port
per attivare una porta per le richiesteHTTP1.1
:- Deployment GKE: segui le istruzioni riportate in Eseguire il deployment dell'API di esempio e di ESP nel cluster, assicurandoti che il flag
"--http_port"
sia specificato nel file di configurazione GKE. - Deployment di Compute Engine: segui le istruzioni riportate in Eseguire l'API e l'ESP di esempio in un contenitore Docker.
Assicurati che il flag
--http_port
sia specificato nel comandodocker run
quando esegui il container Docker ESP precompilato.
- Deployment GKE: segui le istruzioni riportate in Eseguire il deployment dell'API di esempio e di ESP nel cluster, assicurandoti che il flag
Effettuare chiamate HTTP al servizio
- Ottieni l'indirizzo IP esterno dell'ESP e impostalo su
$ESP_IP
. Fai la seguente richiesta HTTP con
curl
curl http://$ESP_IP/v1/shelves
(oppure utilizza lo stesso URL con
https://
se utilizzi SSL). Il server risponde con:{"shelves":[{"id":"1","theme":"Fiction"},{"id":"2","theme":"Fantasy"}]}
Se l'output mostra una risposta binaria, controlla la configurazione della porta perché potresti aver raggiunto la porta HTTP2 anziché la porta HTTP.
Prova un metodo
Create
.CreateShelf
richiede una chiave API, quindi devi crearla per il tuo progetto e impostarla come$KEY
. Chiama ora:curl -d '{"theme":"Music"}' http://$ESP_IP/v1/shelves?key=$KEY
Se chiami di nuovo
GetShelves
, dovresti vedere il nuovo scaffale.