gRPC-Dienst konfigurieren

Wenn Sie einen gRPC-Dienst erstellen, geben Sie unabhängig davon, ob Sie Cloud Endpoints verwenden, die Schnittstellendefinition in einer oder mehreren proto-Dateien an. Dies sind Textdateien mit der Erweiterung .proto. In proto-Dateien definieren Sie die Benutzeroberfläche Ihrer API, einschließlich Datenstrukturen, Methoden, Methodenparametern und Rückgabetypen. Anschließend kompilieren Sie die proto-Datei mit dem sprachspezifischen Protokollpuffer-Compiler protoc. In der Dokumentation zu gRPC finden sie eine Erläuterung zu gRPC und Informationen zu den gRPC-Konzepten.

Damit Ihr gRPC-Dienst von Endpoints verwaltet wird, müssen Sie neben der kompilierten .proto-Datei eine Dienstkonfiguration in einer oder mehreren YAML-Dateien angeben. In einer Dienstkonfiguration können Sie das Verhalten eines gRPC-Dienstes definieren, einschließlich Authentifizierung, Kontingenten usw.

Dienstkonfiguration – Übersicht

Am Anfang der YAML-Datei geben Sie grundlegende Informationen zum Dienst wie dessen Namen und Titel an. In Unterabschnitten der YAML-Datei definieren Sie weitere Aspekte. Zum Beispiel:

Beispiel:

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

Jeder Unterabschnitt entspricht normalerweise einer Nachricht vom Typ .proto message, in der Sie verschiedene Aspekte des Dienstes konfigurieren. Beispiel:

  • authentication: Gibt an, wie Aufrufer authentifiziert werden.
  • backend: steuert das Remote-Backend-Routing.
  • http: Definiert die Regeln für die Zuordnung einer RPC-Methode zu einer oder mehreren HTTP REST API-Methoden.
  • usage: Ermöglicht die selektive Aktivierung und Deaktivierung der Validierung von API-Schlüsseln.

Das offizielle Schema für die Dienstkonfiguration wird durch die .proto-Nachricht google.api.Service definiert.

Grundlegende Konfiguration

Das Bookstore-Beispiel, das in den gRPC-Anleitungen verwendet wird, enthält eine Datei mit einer grundlegenden Schnittstellendefinition und eine Dienstkonfigurationsdatei.

Bookstore-Schnittstellendefinition 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;
}

Bookstore-Dienstkonfiguration 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

Das letzte Codebeispiel ist die einfachste Dienstkonfiguration:

  • Sie definiert einen Dienst mit dem Namen bookstore.endpoints.MY_PROJECT_ID.cloud.goog, wobei MY_PROJECT_ID für Ihre Google Cloud-Projekt-ID steht.
  • Sie legt fest, dass der Dienst die API endpoints.examples.bookstore.Bookstore gemäß Definition in der Datei bookstore.proto bereitstellt.
  • Sie bietet einen beschreibenden Titel, der nach der Bereitstellung der Konfiguration in der Google Cloud Console auf der Seite Endpunkte > Dienste angezeigt wird. Ausführlichere Informationen finden Sie in den vollständigen GitHub-Versionen jeder Datei.

Regeln und Auswahlen

Mitunter muss die Konfiguration einzelnen Elementen eines Diensts zugeordnet werden, um beispielsweise die Authentifizierung für bestimmte Methoden zu erzwingen. Um dies in Ihrer Dienstkonfiguration zu konfigurieren, können Sie in einigen Teilen der Dienstkonfiguration, z. B. authentication und http, Regeln und Selektoren angeben. Ein Selektor identifiziert die Elemente des Dienstes, z. B. einen Methodennamen, auf die die mit der Regel verbundene Konfiguration angewendet wird.

Ein Selektor ist eine durch Kommas getrennte Liste mit qualifizierten Namen, die im Dienst definiert wurden: Methoden, Nachrichten, Felder, Enumerationen oder Enumerationswerte. Das letzte Segment des Namens kann der Platzhalter * sein, der für ein beliebiges Suffix steht. Platzhalter sind nur am Ende eines Namens und nur für ein ganzes Segment des Namens zulässig. Beispiel: foo.* ist zulässig, aber nicht foo.b* oder foo.*.bar. Wenn Sie für alle anwendbaren Elemente einen Standardwert konfigurieren möchten, geben Sie nur * an.

Beispiel 1 (wirkt sich auf den gesamten Dienst aus):

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

Beispiel 2 (wirkt sich auf eine einzelne Methode aus):

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

Das letzte Beispiel zeigt, wie die Validierung der API-Schlüssel für alle Methoden außer der Methode ListShelves vorausgesetzt wird.

Regeln werden sequenziell ausgewertet. Angewendet wird die letzte übereinstimmende Regel in der Deklarationsreihenfolge.

Mehrere YAML-Dateien verwenden

Es kann sinnvoll sein, mehr als eine YAML-Datei zu verwenden, um verschiedene Funktionen für denselben Dienst zu konfigurieren. Wenn Sie mehrere YAML-Dateien verwenden, können Sie Dateien leichter wiederverwenden und für verschiedene Umgebungen anpassen. Im oben aufgeführten Bookstore-Beispiel wird die grundlegende Konfiguration beispielsweise in der Datei api_config.yaml festgelegt. Die HTTP-Regeln werden in der Datei api_config_http.yaml angegeben. Dadurch können Sie die HTTP-Regeln nur bereitstellen, wenn Sie JSON/HTTP für die gRPC-Transcodierung für den Bookstore aktivieren möchten.

Wenn Sie für die Dienstkonfiguration mehrere YAML-Dateien verwenden, werden beim Bereitstellen der Konfiguration alle Dateien in .proto-Nachrichten vom Typ google.api.Service konvertiert. Anschließend erfolgt die Zusammenführung aller Nachrichten mit der entsprechenden Semantik für .proto-Dateien. Dies bedeutet, dass alle einzelnen skalaren Felder in letzterer Instanz die Felder in der vorherigen Instanz ersetzen. Wenn Sie daher für dieselbe Regel in zwei Dateien unterschiedliche Singulärwerte angeben, wird für die Bereitstellung der Konfiguration der Wert in der zweiten Datei verwendet. Außerdem werden einzelne eingebettete Nachrichten zusammengeführt und sich wiederholende Felder verkettet.

Wie bei Regeln wird auch bei Zusammenführungen die Reihenfolge berücksichtigt. Wenn zwei Dienstkonfigurationen vorhanden sind, überschreibt die zweite Dienstkonfiguration die erste.

Annotationen (nur HTTP-Regeln)

Alternativ zu einer YAML-Datei können Sie HTTP-Optionen mithilfe des Optionsmechanismus auch direkt in der proto-Datei konfigurieren. API-Annotationen werden in annotations.proto definiert.

Nutzen Sie Annotationen, wenn die Konfigurationsoption bei allen Verwendungen der API-Definition für den Protokollzwischenspeicher unverändert bleiben soll. Wenn eine API beispielsweise nur einmal implementiert wurde oder alle Implementierungen dieselbe HTTP-Oberfläche benötigen, kann die HTTP-Konfiguration in der proto-Datei annotiert werden.

Wenn sowohl in der proto-Datei als auch in der YAML-Dienstkonfigurationsdatei eine Konfigurationsoption angegeben ist, überschreibt die YAML-Konfiguration die Annotation.

Beispielannotation in einer proto-Datei:

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'

Weitere Informationen finden Sie unter HTTP/JSON zu gRPC transcodieren.

Konfigurationsprüfung

Für die Bereitstellung Ihrer Dienstkonfiguration und der kompilierten proto-Dateien verwenden Sie gcloud endpoints services deploy, um die Laufzeitkonfiguration des Dienstes zu erstellen. Mit dem Befehl gcloud endpoints services deploy wird die Dienstkonfiguration validiert. Fehler und Warnungen werden gemeldet.

Warnungen werden in reguläre und Linter-Warnungen unterteilt. Linter-Warnungen verwenden als Kennung <group>-<rule>, wobei <group> die Konfigurationsgruppe und <rule> die spezielle Linter-Regel angibt. Im folgenden Beispiel wird als Gruppe versioning und als Regel http-version-prefix verwendet:

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'.

Sie können Linter-Warnungen unterdrücken, indem Sie der Dokumentation eines API-Elements eine Anweisung hinzufügen. Die Anweisung fügen Sie entweder in Ihrer proto-Datei oder in der YAML-Dienstkonfigurationsdatei hinzu. Die folgende Anweisung unterdrückt beispielsweise die obige Warnung:

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" };
  }
}

Um Warnungen für eine ganze Gruppe zu unterdrücken, können Sie anstelle von Regelnamen den Platzhalter * verwenden. Mit versioning-* unterdrücken Sie beispielsweise alle Warnungen bezüglich der Gruppe versioning.

Unterdrückungsanweisungen, die Sie übergeordneten Elementen hinzufügen, gelten auch für alle untergeordneten Elemente. Das folgende Beispiel unterdrückt alle Warnungen für die Gruppe versioning für alle Methoden innerhalb des Dienstes:

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

Wenn Sie eine Warnung global unterdrücken möchten, fügen Sie sie der allgemeinen Dokumentation der Dienstkonfiguration hinzu:

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 ==)

Anweisungen wie suppress_warning müssen in Dokumentationen in einer eigenen Zeile stehen, da sie andernfalls nicht erkannt werden. Markierungen wie > für YAML-Blockliterale entfernen alle neuen Zeilen. Wenn Sie im vorangegangenen Beispiel overview: > verwendet haben, funktioniert die Unterdrückung nicht. Weitere Informationen zu Blockliteralen in YAML finden Sie in der YAML-Dokumentation im Abschnitt zu eingerückten Begrenzungen.

Nächste Schritte