Configurar um serviço gRPC

Para criar um serviço gRPC, quer esteja ou não a usar o API Gateway, tem de especificar a definição da interface num ou mais ficheiros proto, que são ficheiros de texto com a extensão .proto. Num ficheiro proto, define a superfície da sua API, incluindo as estruturas de dados, os métodos, os parâmetros dos métodos e os tipos de retorno. Em seguida, compila o ficheiro proto com o compilador de buffers de protocolo específico do idioma, protoc. Para mais informações, consulte os artigos O que é o gRPC? e Conceitos do gRPC.

Para que o seu serviço gRPC seja gerido pela API Gateway, além do ficheiro proto compilado, tem de especificar uma configuração do serviço num ou mais ficheiros YAML. Uma configuração de serviço é uma especificação que lhe permite definir o comportamento de um serviço gRPC, incluindo autenticação, quotas e muito mais.

Vista geral da configuração do serviço

Na parte superior do ficheiro YAML, pode especificar informações básicas sobre o serviço, como o nome e o título. Outros aspetos do serviço são configurados em subseções do ficheiro YAML, por exemplo:

Por exemplo:

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

Normalmente, cada subsecção corresponde a uma mensagem .proto onde configura vários aspetos do serviço. Por exemplo:

  • authentication: especifica como os autores das chamadas são autenticados.
  • backend: controla o encaminhamento do back-end remoto.
  • http: define as regras para mapear um método RPC para um ou mais métodos da API REST HTTP.
  • usage: permite ativar e desativar seletivamente a validação da chave da API.

O esquema oficial da configuração do serviço é definido pela .proto mensagem google.api.Service.

Configuração básica

O exemplo da livraria, que é usado no tutorial Introdução ao API Gateway e ao Cloud Run para gRPC, inclui um ficheiro de definição de interface básico e um ficheiro de configuração de serviço.

A definição da interface da livraria, 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;
}

A configuração do serviço Bookstore, api_config.yaml:

type: google.api.Service
config_version: 3

name: *.apigateway.PROJECT_ID.cloud.goog

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

O exemplo de código anterior é a configuração de serviço mais simples, uma vez que:

  • Define um serviço denominado *.apigateway.PROJECT_ID.cloud.goog onde PROJECT_ID é o nome do seu Google Cloud ID do projeto.
  • Especifica que o serviço expõe a API endpoints.examples.bookstore.Bookstore, conforme definido no ficheiro bookstore.proto.

Regras e seletores

Em alguns casos, pode precisar da capacidade de associar a configuração a elementos individuais de um serviço, por exemplo, para aplicar a autenticação a determinados métodos, mas não a outros. Para configurar esta opção na configuração do serviço, algumas partes da configuração do serviço, como authentication e http, permitem-lhe especificar regras e seletores. Um seletor identifica os elementos do serviço, como um nome de método ao qual a configuração associada à regra se aplica.

Um seletor é uma lista de nomes qualificados separados por vírgulas definidos no serviço: método, mensagem, campo, enumeração ou valores de enumeração. O último segmento do nome pode ser o caráter universal *, que corresponde a qualquer sufixo. Os carateres universais só são permitidos no final de um nome e apenas para um segmento completo do nome. Por exemplo: foo.* é aceitável, mas foo.b* ou foo.*.bar não. Para configurar um valor predefinido para todos os elementos aplicáveis, especifique * sozinho.

Exemplo 1 (que afeta todo o serviço):

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

Exemplo 2 (que afeta um único método):

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

O exemplo anterior mostra como exigir a validação da chave da API para todos os métodos, exceto o método ListShelves.

As regras são avaliadas sequencialmente e é aplicada a última regra correspondente na ordem de declaração.

Usar vários ficheiros YAML

Pode ser útil usar mais do que um ficheiro YAML para configurar diferentes funcionalidades para o mesmo serviço. A utilização de vários ficheiros YAML facilita a reutilização de ficheiros e a respetiva modificação para diferentes ambientes. Por exemplo, no exemplo da livraria, a configuração básica é especificada no ficheiro api_config.yaml e as respetivas regras HTTP são especificadas no ficheiro api_config_http.yaml. Isto permite-lhe implementar as regras HTTP apenas se quiser ativar a transcodificação JSON/HTTP para gRPC para a Bookstore.

Se usar vários ficheiros YAML para a configuração do serviço, quando a configuração é implementada, cada ficheiro é convertido em mensagens proto google.api.Service e, em seguida, todas as mensagens são unidas através da semântica de união de proto. Ou seja, todos os campos escalares singulares na última instância substituem os da instância anterior. Assim, se fornecer valores singulares diferentes para a mesma regra em dois ficheiros, é usado o valor no segundo ficheiro que especificar quando implementar a configuração. As mensagens incorporadas singulares são unidas e os campos repetidos são concatenados.

Tal como as regras, a união é sensível à ordem. Se existirem duas configurações de serviço, a segunda configuração de serviço substitui a primeira.

Anotações (apenas regras HTTP)

Em alternativa à utilização de um ficheiro YAML para configurar as opções HTTP, pode configurá-las diretamente no ficheiro proto através do mecanismo de opções. As anotações da API estão definidas em annotations.proto.

Use anotações se a opção de configuração se destinar a ser invariante em todas as utilizações da definição da interface do buffer de protocolo. Por exemplo, se uma API tiver uma única implementação ou todas as implementações tiverem de ter a mesma interface HTTP, pode anotar a configuração HTTP no ficheiro proto.

Se for fornecida uma opção de configuração no ficheiro proto e no ficheiro YAML de configuração do serviço, a configuração do serviço substitui a anotação.

Exemplo de anotação num ficheiro 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'

Para mais informações, consulte o artigo Transcodificação de HTTP/JSON para gRPC.

O que se segue?