Configurer un service gRPC

Pour créer un service gRPC, que vous utilisiez ou non Cloud Endpoints, vous devez indiquer la définition de l'interface dans un ou plusieurs fichiers proto, qui sont des fichiers texte portant l'extension .proto. Dans un fichier proto, vous définissez la surface de votre API, y compris les structures de données, les méthodes, les paramètres de méthode et les types de renvois. Vous compilez ensuite votre fichier proto à l'aide du tampon de protocole spécifique au langage, protoc. Pour plus d'informations, consultez les sections Qu'est-ce que gRPC ? et Concepts de gRPC.

Pour que votre service gRPC soit géré par Cloud Endpoints, outre le fichier proto compilé, vous devez spécifier une configuration de service dans un ou plusieurs fichiers YAML. Une configuration de service est une spécification qui vous permet de définir le comportement d'un service gRPC, y compris l'authentification, les quotas, etc.

Présentation de la configuration de service

En haut du fichier YAML, spécifiez des informations de base du service, telles que son nom et son titre. Configurez d'autres aspects du service dans les sous-sections du fichier YAML, par exemple :

Exemple :

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

Chaque sous-section correspond généralement à un message .proto dans lequel vous configurez divers aspects du service. Exemple :

  • authentication : spécifie la manière dont les appelants sont authentifiés.
  • backend : contrôle le routage du backend distant.
  • http : définit les règles pour mapper une méthode RPC sur une ou plusieurs méthodes API HTTP REST.
  • usage : permet d'activer et de désactiver de manière sélective la validation des clés API.

Le schéma officiel de la configuration de service est défini par le message .proto google.api.Service.

Configuration de base

L'exemple Bookstore, utilisé dans les tutoriels gRPC, comprend un fichier de définition d'interface de base et un fichier de configuration de service.

Définition de l'interface 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;
}

Configuration de service Bookstore, 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'exemple de code précédent est la configuration de service la plus simple :

  • Elle définit un service nommé bookstore.endpoints.MY_PROJECT_ID.cloud.goog, où MY_PROJECT_ID représente l'ID de votre projet Google Cloud.
  • Elle indique que le service expose l'API endpoints.examples.bookstore.Bookstore, comme défini dans le fichier bookstore.proto.
  • Elle fournit un titre descriptif qui apparaît sur la page Endpoints > Services de la console Google Cloud après le déploiement de la configuration. Examinez les versions GitHub complètes de chaque fichier pour des commentaires plus détaillés.

Règles et sélecteurs

Dans certains cas, vous aurez peut-être besoin d'associer une configuration aux éléments individuels d'un service, par exemple, pour appliquer l'authentification à certaines méthodes mais pas à d'autres. Pour que vous puissiez configurer cela dans votre configuration de service, certaines parties de la configuration de service, telles que authentication et http, permettent de spécifier des règles et des sélecteurs. Un sélecteur identifie les éléments du service (par exemple, le nom de la méthode) auxquels la configuration associée à la règle s'applique.

Un sélecteur est une liste d'éléments séparés par une virgule de noms qualifiés dans le service : méthode, message, champ, énumération ou valeurs d'énumération. Le dernier segment du nom peut être le caractère générique *, qui correspond à n'importe quel suffixe. Les caractères génériques sont autorisés uniquement à la fin d'un nom et uniquement pour un segment entier du nom. Par exemple, foo.* est accepté, mais foo.b* ou foo.*.bar ne le sont pas. Pour configurer une valeur par défaut pour tous les éléments applicables, vous devez spécifier * par lui-même.

Exemple 1 (concernant l'ensemble du service) :

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

Exemple 2 (concernant une seule méthode) :

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'exemple précédent montre comment exiger la validation de la clé API pour toutes les méthodes, à l'exception la méthode ListShelves.

Les règles sont évaluées séquentiellement, la dernière à correspondre dans l'ordre de déclaration est appliqué.

Utiliser plusieurs fichiers YAML

Vous trouverez peut-être utile d'utiliser plusieurs fichiers YAML pour configurer différentes fonctionnalités pour le même service. Le fait d'utiliser plusieurs fichiers YAML facilite leur réutilisation et leur modification pour différents environnements. Par exemple, dans l'exemple Bookstore, la configuration de base est spécifiée dans le fichier api_config.yaml, et ses règles HTTP dans le fichier api_config_http.yaml. Cela vous permet de déployer les règles HTTP uniquement si vous souhaitez activer le transcodage JSON/HTTP vers gRPC pour le Bookstore.

Si vous utilisez plusieurs fichiers YAML pour votre configuration de service, le traitement effectué lors du déploiement de la configuration est le suivant : les fichiers sont convertis en messages proto google.api.Service, puis tous les messages sont fusionnés à l'aide de la sémantique de fusion proto. En d'autres termes, tous les champs scalaires singuliers de la dernière instance remplacent ceux de la première. Ainsi, si vous fournissez différentes valeurs singulières pour la même règle dans deux fichiers, la valeur du deuxième fichier que vous spécifiez lors du déploiement de la configuration est utilisée. Les messages intégrés singuliers sont fusionnés et les champs répétés sont concaténés.

Comme les règles, la fusion est sensible à l'ordre. S'il existe deux configurations de service, la deuxième configuration de service a la priorité sur la première.

Annotations (règles HTTP uniquement)

Au lieu d'utiliser un fichier YAML pour configurer les options HTTP, vous pouvez les configurer directement dans votre fichier proto en utilisant le mécanisme des options. Les annotations d'API sont définies dans le fichier annotations.proto.

Utilisez des annotations si l'option de configuration est destinée à être invariante dans toutes les utilisations de la définition d'interface de tampon de protocole. Par exemple, si une API possède une seule mise en œuvre ou si toutes les mises en œuvre doivent avoir la même interface HTTP, la configuration HTTP peut être annotée dans le fichier proto.

Si une option de configuration est fournie à la fois dans le fichier proto et dans le fichier YAML de configuration de service, la configuration de service remplace l'annotation.

Exemple d'annotation dans un fichier 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'

Pour plus d'informations, consultez la section Transcoder HTTP/JSON vers gRPC.

Validation de la configuration

Vous déployez votre configuration de service et vos fichiers proto compilés à l'aide de la commande gcloud endpoints services deploy pour créer la configuration d'exécution de votre service. La commande gcloud endpoints services deploy valide la configuration de service et signale tout avertissement et toute erreur potentiels.

Les avertissements sont divisés en avertissements standards et avertissements linter. Les avertissements linter utilisent un identifiant de la forme <group>-<rule>, où <group> indique le groupe de configuration et <rule> la règle linter particulière. Par exemple, ci-dessous, le groupe correspond à versioning et la règle à 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'.

Vous pouvez supprimer les avertissements linter en ajoutant une directive à la documentation d'un élément d'API. Vous pouvez ajouter la directive dans votre fichier proto ou dans le fichier YAML de configuration de service. Par exemple, l'élément suivant permet de supprimer l'avertissement ci-dessus :

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

Pour supprimer les avertissements d'un groupe entier, vous pouvez utiliser un caractère générique (*) au lieu de noms de règles. Par exemple, versioning-* supprime tous les avertissements liés au groupe de versioning.

Les directives de suppression jointes aux éléments parents s'appliquent également à tous les enfants. Par exemple, l'exemple suivant supprime tous les avertissements du groupe de versioning sur toutes les méthodes du service :

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

Pour supprimer un avertissement de manière globale, joignez-le à la documentation de présentation de la configuration du service :

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

Notez que les directives dans la documentation telles que suppress_warning doivent apparaître sur leur propre ligne, sinon elles ne seront pas reconnues. Les repères littéraux de bloc YAML tels que > suppriment toutes les nouvelles lignes. Ainsi, si vous utilisez overview: > dans l'exemple ci-dessus, la suppression ne fonctionne pas. Pour plus d'informations sur les littéraux de bloc en YAML, consultez la section Indented delimiting (délimitation en retrait).

Étapes suivantes