Configurazione di un servizio gRPC

Per creare un servizio gRPC, indipendentemente dal fatto che utilizzi Cloud Endpoints o meno, devi specificare la definizione dell'interfaccia in uno o più proto file, che sono file di testo con estensione .proto. In un file proto, definisci la superficie dell'API, compresi le strutture di dati, i metodi, i parametri dei metodi e i tipi di ritorno. Poi devi compilare il tuo file proto utilizzando il compilatore del buffer di protocollo specifico per la lingua, protoc. Per ulteriori informazioni, consulta Che cos'è gRPC? e concetti di gRPC.

Per fare in modo che il servizio gRPC venga gestito da Endpoints, oltre al file di protocollo compilato, devi specificare una configurazione del servizio in uno o più file YAML. Una configurazione del servizio è una specifica che consente di definire il comportamento di un servizio gRPC, incluse autenticazione, quote e altro.

Panoramica della configurazione del servizio

Nella parte superiore del file YAML, devi specificare le informazioni di base sul servizio, come il nome e il titolo. Puoi configurare altri aspetti del servizio nelle sottosezioni del file YAML, ad esempio:

Ad esempio:

type: google.api.Service
config_version: 3
name: calendar.googleapis.com
title: Google Calendar API
apis:
- name: google.calendar.v3.Calendar
authentication:
  providers:
  - id: google_calendar_auth
    jwks_uri: https://www.googleapis.com/oauth2/v1/certs
    issuer: https://securetoken.google.com
  rules:
  - selector: "*"
    requirements:
      provider_id: google_calendar_auth
backend:
  rules:
    - selector: "*"
      address: grpcs://my-service-98sdf8sd0-uc.a.run.app

Ogni sottosezione corrisponde in genere a un messaggio .proto in cui configuri i vari aspetti del servizio. Ad esempio:

  • authentication: specifica come vengono autenticati i chiamanti.
  • backend: controlla il routing del backend remoto.
  • http: definisce le regole per la mappatura di un metodo RPC a uno o più metodi dell'API REST HTTP.
  • usage: consente di abilitare e disabilitare in modo selettivo la convalida delle chiavi API.

Lo schema ufficiale per la configurazione del servizio è definito dal messaggio .proto google.api.Service.

Configurazione di base

L'esempio di Bookstore, utilizzato nei tutorial su gRPC, include un file di definizione dell'interfaccia di base e un file di configurazione del servizio.

Definizione dell'interfaccia Bookstore, bookstore.proto:

syntax = "proto3";

package endpoints.examples.bookstore;

option java_multiple_files = true;
option java_outer_classname = "BookstoreProto";
option java_package = "com.google.endpoints.examples.bookstore";

import "google/protobuf/empty.proto";

service Bookstore {
  rpc ListShelves(google.protobuf.Empty) returns (ListShelvesResponse) {}
  rpc CreateShelf(CreateShelfRequest) returns (Shelf) {}
  rpc GetShelf(GetShelfRequest) returns (Shelf) {}
  rpc DeleteShelf(DeleteShelfRequest) returns (google.protobuf.Empty) {}
  rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {}
  rpc CreateBook(CreateBookRequest) returns (Book) {}
  rpc GetBook(GetBookRequest) returns (Book) {}
  rpc DeleteBook(DeleteBookRequest) returns (google.protobuf.Empty) {}
}

message Shelf {
  int64 id = 1;
  string theme = 2;
}

message Book {
  int64 id = 1;
  string author = 2;
  string title = 3;
}

La configurazione del servizio Libreria, api_config.yaml:

type: google.api.Service
config_version: 3

name: bookstore.endpoints.MY_PROJECT_ID.cloud.goog

title: Bookstore gRPC API
apis:
- name: endpoints.examples.bookstore.Bookstore

L'esempio di codice precedente è la configurazione del servizio più semplice, in quanto:

  • Definisce un servizio denominato bookstore.endpoints.MY_PROJECT_ID.cloud.goog, dove MY_PROJECT_ID rappresenta il tuo ID progetto Google Cloud.
  • Specifica che il servizio espone l'API endpoints.examples.bookstore.Bookstore, come definito nel file bookstore.proto.
  • Fornisce un titolo descrittivo che viene visualizzato nella pagina Endpoint > Servizi della console Google Cloud dopo aver eseguito il deployment della configurazione. Esamina le versioni GitHub complete di ogni file per commenti più dettagliati.

Regole e selettori

In alcuni casi, potrebbe essere necessaria la possibilità di associare la configurazione a singoli elementi di un servizio, ad esempio per applicare l'autenticazione su determinati metodi e non su altri. Per configurarlo nella configurazione del servizio, alcune parti della configurazione del servizio, come authentication e http, consentono di specificare regole e selettori. Un selettore identifica gli elementi del servizio, ad esempio un nome del metodo a cui si applica la configurazione associata alla regola.

Un selettore è un elenco separato da virgole di nomi qualificati definiti nel servizio: valori di metodo, messaggio, campo, enum o enum. L'ultimo segmento del nome può essere il carattere jolly *, che corrisponde a qualsiasi suffisso. I caratteri jolly sono consentiti solo alla fine di un nome e solo per un intero segmento del nome. Ad esempio: foo.* va bene, ma non foo.b* o foo.*.bar. Per configurare un valore predefinito per tutti gli elementi applicabili, devi specificare * da solo.

Esempio 1 (interessato all'intero servizio):

usage:
  rules:
  # Allow unregistered calls for all methods.
  - selector: "*"
    allow_unregistered_calls: true

Esempio 2 (che interessa un singolo metodo):

usage:
  rules: # IMPORTANT: ONLY LAST MATCHING RULE IS APPLIED
  # Disable API key validation on just the ListShelves method
  # while requiring an API key for the rest of the API.
  - selector: "*"
    allow_unregistered_calls: false
  - selector: "endpoints.examples.bookstore.BookStore.ListShelves"
    allow_unregistered_calls: true

L'esempio precedente mostra come richiedere la convalida delle chiavi API per tutti i metodi tranne il metodo ListShelves.

Le regole vengono valutate in sequenza e viene applicata l'ultima corrispondenza nell'ordine di dichiarazione.

Utilizzo di più file YAML

Potresti trovare utile utilizzare più file YAML per configurare funzionalità diverse per lo stesso servizio. Usare più file YAML semplifica il riutilizzo dei file e la loro modifica per ambienti diversi. Ad esempio, nell'esempio di Bookstore, la configurazione di base è specificata nel file api_config.yaml e le relative regole HTTP sono specificate nel file api_config_http.yaml. In questo modo puoi eseguire il deployment delle regole HTTP solo se vuoi attivare la transcodifica da JSON/HTTP a gRPC per il Bookstore.

Se utilizzi più file YAML per la configurazione del servizio, quando la configurazione viene implementata, ogni file viene convertito in messaggi proto google.api.Service e tutti i messaggi vengono uniti utilizzando la semantica dell'unione dei proto. Ciò significa che tutti i campi scalari singolari dell'ultima istanza sostituiscono quelli della precedente. Pertanto, se fornisci valori singolari diversi per la stessa regola in due file, viene utilizzato il valore nel secondo file specificato durante il deployment della configurazione. I messaggi incorporati singolari vengono uniti e i campi ripetuti vengono concatenati.

Come per le regole, l'unione è sensibile all'ordine. Se esistono due configurazioni di servizio, la seconda configurazione del servizio#39;override della prima.

Annotazioni (solo regole HTTP)

In alternativa all'utilizzo di un file YAML per la configurazione delle opzioni HTTP, puoi configurarle direttamente nel file proto, utilizzando il meccanismo delle opzioni. Le annotazioni API sono definite in annotations.proto.

Utilizza le annotazioni se l'opzione di configurazione deve essere invariante rispetto a tutti gli utilizzi della definizione dell'interfaccia del buffer di protocollo. Ad esempio, se un'API ha un'unica implementazione o se tutte le implementazioni devono avere la stessa interfaccia HTTP, puoi annotare la configurazione HTTP nel file proto.

Se viene fornita un'opzione di configurazione, sia nel file proto sia nel file YAML di configurazione del servizio, la configurazione del servizio sostituisce l'annotazione.

Esempio di annotazione in un file proto:

rpc ListShelves(google.protobuf.Empty) returns (ListShelvesResponse) {
    option (google.api.http) = { get: "/v1/shelves" };
}

# The preceding annotation is equivalent to the following service configuration:

http:
  rules:
  - selector: endpoints.examples.bookstore.BookStore.ListShelves
    get: '/v1/shelves'

Per maggiori informazioni, consulta Transcodifica di HTTP/JSON in gRPC.

Convalida della configurazione

Per eseguire il deployment della configurazione del servizio e della compilazione di proto file, utilizza gcloud endpoints services deploy per creare la configurazione di runtime del servizio. Il comando gcloud endpoints services deploy convalida la configurazione del servizio e segnala eventuali errori e avvisi.

Gli avvisi sono suddivisi in avvisi regolari e avvisi linter. Gli avvisi di linter utilizzano un identificatore nel formato <group>-<rule>, dove <group> indica il gruppo di configurazione e <rule> la regola di linter specifica. Ad esempio, di seguito il gruppo è versioning e la regola è http-version-prefix:

WARNING: bookstore.proto:51:3: (lint) versioning-http-version-prefix: method
'endpoints.examples.bookstore.BookStore.ListShelves' has a different version
prefix in HTTP path ('v2') than api version 'v1'.

Puoi eliminare gli avvisi linter aggiungendo un'istruzione alla documentazione di un elemento API. Puoi aggiungere l'istruzione nel file proto o nel file YAML di configurazione del servizio. Ad esempio, quanto segue elimina l'avviso precedente:

service Bookstore {
  // Returns an object.
  // (== suppress_warning versioning-http-version-prefix ==)
  rpc ListShelves(google.protobuf.Empty) returns (ListShelvesResponse) {
      option (google.api.http) = { get: "/v1/shelves" };
  }
}

Per eliminare gli avvisi per un intero gruppo, puoi utilizzare un carattere jolly (*) anziché i nomi delle regole. Ad esempio, versioning-* elimina tutti gli avvisi relativi al gruppo versioning.

Le istruzioni di eliminazione collegate agli elementi principali si applicano anche a tutti gli elementi secondari. Ad esempio, l'esempio seguente elimina tutti gli avvisi del gruppo versioning in tutti i metodi all'interno del servizio:

// (== suppress_warning versioning-* ==)
service Bookstore {
  // Returns an object.
  rpc ListShelves(google.protobuf.Empty) returns (ListShelvesResponse) {
      option (google.api.http) = { get: "/v1/shelves" };
  }
}

Per eliminare un avviso a livello globale, allegalo alla documentazione di riepilogo della configurazione del servizio:

type: google.api.Service
name: your_api.endpoints.<producer-project-id>.cloud.goog
title: Bookstore gRPC API
apis:
- name: endpoints.examples.bookstore.BookStore
documentation:
    overview: |
      A simple Bookstore gRPC API.
      (== suppress_warning documentation-presence ==)

Tieni presente che le istruzioni nella documentazione, come suppress_warning, devono essere inserite in una propria riga, altrimenti non saranno riconosciute. Gli indicatori dei valori letterali a blocchi YAML, come >, rimuovono tutti i ritorni a capo; quindi, se utilizzi overview: > nell'esempio precedente, l'eliminazione non funziona. Per ulteriori informazioni sui valori letterali a blocco in YAML, consulta la pagina Delimitazione con rientro.

Passaggi successivi