Como configurar um serviço gRPC

Para criar um serviço gRPC, mesmo que você não use o Cloud Endpoints, especifique a definição da interface em um ou mais arquivos proto, que são arquivos de texto com a extensão .proto. Em um arquivo proto, você define a superfície da API, incluindo as estruturas de dados, os métodos, os parâmetros do método e os tipos de retorno. Em seguida, compile seu arquivo proto usando o compilador de buffer de protocolo específico da linguagem, protoc. Para mais informações, consulte O que é gRPC? e Conceitos de gRPC (links em inglês).

Para que o serviço gRPC seja gerenciado pelo Endpoints, além do arquivo proto compilado, é preciso especificar uma configuração de serviço em um ou mais arquivos YAML. Uma configuração de serviço é uma especificação que permite definir o comportamento de um serviço gRPC, incluindo autenticação, cotas e muito mais.

Visão geral da configuração de serviço

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

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 subseção corresponde a uma mensagem .proto (em inglês), em que vários aspectos do serviço são configurados. Exemplo:

  • authentication: especifica como os chamadores são autenticados.
  • backend: controla o roteamento remoto de back-end.
  • 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 de API.

O esquema oficial da configuração do serviço é definido pela mensagem .proto google.api.Service (em inglês).

Configuração básica

O exemplo do Wallet (em inglês), usado no tutorial Primeiros passos com o gateway de API e o Cloud Run for gRPC (em inglês), inclui uma explicação básica , além de um arquivo de configuração de serviço.

A definição da interface Bookstore, bookstore.proto (em inglês):

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 (em inglês):

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, já que:

  • Define um serviço chamado *.apigateway.PROJECT_ID.cloud.goog, em que PROJECT_ID é o nome do ID do projeto do Google Cloud.
  • especifica que o serviço expõe a API endpoints.examples.bookstore.Bookstore, conforme definido no arquivo bookstore.proto;

Regras e seletores

Em alguns casos, será preciso associar a configuração a elementos individuais de um serviço. Por exemplo, para impor a autenticação em determinados métodos, mas não em outros. Para fazer isso na configuração do serviço, algumas partes dela, como authentication e http, permitem especificar regras e seletores. Um seletor identifica os elementos do serviço, como um nome de método a que a configuração associada à regra se aplica.

Um seletor é uma lista separada por vírgulas de nomes qualificados de serviço, método, mensagem, campo, "enum" ou valores de "enum". O último segmento do nome pode ser o caractere curinga *, que corresponde a qualquer sufixo. Caracteres curinga são permitidos apenas no final de um nome e apenas para um segmento inteiro do nome. Por exemplo: foo.* está correto, mas não foo.b* ou foo.*.bar. Para configurar um padrão para todos os elementos aplicáveis, especifique * por si só.

Exemplo 1 (afeta todo o serviço):

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

Exemplo 2 (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 de chave de API para todos os métodos, exceto o ListShelves.

As regras são avaliadas sequencialmente, o último correspondente na ordem de declaração é aplicado.

Como usar vários arquivos YAML

Pode ser útil usar mais de um arquivo YAML para configurar recursos diferentes para o mesmo serviço. O uso de vários arquivos YAML facilita a reutilização e modificação de arquivos para diferentes ambientes. Por exemplo, no exemplo do Bookstore, a configuração básica é especificada no arquivo api_config.yaml e suas regras HTTP estão no arquivo api_config_http.yaml (links em inglês). Isso só permite implantar as regras de HTTP se você quiser ativar o JSON/HTTP para transcodificação de gRPC para a Bookstore.

Se você usar vários arquivos YAML para a configuração do serviço, quando a configuração for implantada, cada arquivo será convertido em mensagens proto de google.api.Service (em inglês). Todas as mensagens serão mescladas usando proto mesclando semântica. Ou seja, todos os campos escalares singulares da última instância substituirão os da primeira. Portanto, ao fornecer diferentes valores singulares para a mesma regra em dois arquivos, o valor no segundo arquivo especificado ao implantar a configuração será usado. Mensagens incorporadas singulares serão mescladas e campos repetidos serão concatenados.

Assim como as regras, a mesclagem é sensível à ordem. Se houver duas configurações de serviço, a segunda substituirá a primeira.

Anotações (apenas regras HTTP)

Em vez de usar um arquivo YAML para configurar as opções de HTTP, é possível fazer isso diretamente no arquivo proto, usando o mecanismo de opções (em inglês). As anotações da API estão definidas em annotations.proto (em inglês).

Use anotações se a opção de configuração for invariável ao longo de todos os usos da definição de interface do buffer de protocolo. Por exemplo, se uma API tiver uma única implementação ou todas as implementações forem obrigadas a ter a mesma interface HTTP, anote a configuração de HTTP no arquivo proto.

Se uma opção de configuração for fornecida, tanto no arquivo proto quanto no YAML da configuração de serviço, ela substituirá a anotação.

Anotação de exemplo em um arquivo 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 Como transcodificar HTTP/JSON para gRPC.

A seguir