Serviços gRPC exigem bibliotecas de cliente dedicadas, o que dificulta chamadas a partir de clientes baseados em REST, aplicativos de navegador ou sistemas de terceiros compatíveis apenas com HTTP/JSON. A Custom Resource Definition (CRD) ASMGrpcJsonTranscoder configura os ingress gateways no Service Mesh (ASM) para aceitar requisições HTTP/JSON e transcodificá-las em chamadas gRPC na camada do gateway. Não é necessário alterar o código da aplicação — clientes REST acessam serviços gRPC por meio de endpoints HTTP padrão.
Este guia apresenta a configuração completa: anotação de um arquivo .proto com mapeamentos HTTP, geração de um descritor proto, criação do recurso ASMGrpcJsonTranscoder e verificação do resultado.
Como funciona
O ingress gateway gerencia toda a transcodificação. Além da anotação no arquivo .proto, nenhuma alteração no nível da aplicação é necessária.
|
Fase |
O que acontece |
|
1. Configuração |
O plano de controle do ASM envia três recursos ao ingress gateway: um filtro Envoy para transcodificação gRPC, um gateway Istio e um serviço virtual que roteia o tráfego para a porta do serviço gRPC. O gateway carrega essas configurações imediatamente. |
|
2. Caminho da requisição |
O gateway recebe uma requisição HTTP/JSON, aplica as regras de roteamento, transcodifica a requisição para gRPC e a encaminha ao serviço gRPC de destino. |
|
3. Caminho da resposta |
O gateway recebe a resposta gRPC do serviço de backend, transcodifica-a de volta para HTTP/JSON e a retorna ao cliente. |
Pré-requisitos
Antes de começar, certifique-se de ter:
Uma instância do ASM da Enterprise Edition ou Ultimate Edition. Consulte Criar uma instância do ASM
Um cluster adicionado à instância do ASM
Um serviço de exemplo gRPC implantado no cluster. Consulte Usar um ingress gateway para acessar um serviço gRPC em uma instância do ASM
Protocol Buffers (
protoc) instalado localmente
Adicione anotações HTTP e gere um descritor proto
Para mapear um endpoint HTTP a um método gRPC, adicione uma anotação google.api.http no arquivo .proto e compile-o em um arquivo .proto-descriptor que o filtro Envoy lê em tempo de execução.
Anote o arquivo .proto
Adicione uma opção google.api.http a cada método RPC que deve aceitar requisições HTTP/JSON. A anotação a seguir mapeia GET /sayHello/{name} para o RPC SayHello:
option(google.api.http) = {
get: "/sayHello/{name}"
};
A variável de caminho {name} se vincula ao campo name em HelloRequest. A anotação exige a importação de google/api/annotations.proto.
Este exemplo utiliza o serviço helloworld do grpc.io. Salve o conteúdo a seguir como helloworld.proto:
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package helloworld;
import "google/api/annotations.proto";
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {
option(google.api.http) = {
get: "/sayHello/{name}"
};
}
rpc SayHelloStreamReply (HelloRequest) returns (stream HelloReply) {}
rpc SayHelloBidiStream (stream HelloRequest) returns (stream HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings.
message HelloReply {
string message = 1;
}
Gere o arquivo .proto-descriptor
-
Clone o repositório googleapis, que fornece a definição da anotação
google.api.http:git clone https://github.com/googleapis/googleapis.git -
Execute o
protocpara gerar o descritor:# Set the path to the directory containing helloworld.proto proto_path=<path/to/helloworld-grpc>/grpc/proto # Set the path to the cloned googleapis directory GOOGLEAPIS_DIR=<path/to/googleapis> protoc \ --proto_path=${proto_path} \ --proto_path=${GOOGLEAPIS_DIR} \ --include_imports \ --include_source_info \ --descriptor_set_out=helloworld.proto-descriptor \ "${proto_path}"/helloworld.protoSubstitua os espaços reservados a seguir pelos valores reais:
Espaço reservado
Descrição
Exemplo
<path/to/helloworld-grpc>Diretório raiz do projeto gRPC helloworld
/home/user/helloworld-grpc<path/to/googleapis>Diretório onde você clonou o googleapis
/home/user/googleapisApós a execução bem-sucedida do comando, um arquivo
helloworld.proto-descriptorserá criado no diretório atual.
Crie o recurso ASMGrpcJsonTranscoder
A CRD ASMGrpcJsonTranscoder instrui o plano de controle do ASM a configurar a transcodificação gRPC-JSON no ingress gateway.
-
Salve o YAML a seguir como
grpcjsontranscoder-helloworld.yaml:apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMGrpcJsonTranscoder metadata: name: grpcjsontranscoder-helloworld namespace: istio-system spec: isGateway: true # Apply the transcoder to the ingress gateway portNumber: 8080 # Port for HTTP/JSON requests workloadSelector: labels: istio: ingressgateway # Target the default ingress gateway printOptions: addWhitespace: true # Pretty-print JSON responses alwaysPrintEnumsAsInts: false # Print enum names instead of integer values alwaysPrintPrimitiveFields: false # Omit fields with default values from responses preserveProtoFieldNames: false # Use camelCase field names (protobuf default) priority: 0 services: - helloworld.Greeter # Fully qualified gRPC service name (<package>.<service>) -
Revise os campos principais:
Campo
Descrição
Padrão
isGatewayDefina como
truepara aplicar o transcodificador no ingress gateway em vez de nos proxies sidecar.falseportNumberPorta no ingress gateway que aceita requisições HTTP/JSON.
--
workloadSelector.labelsSeletor de rótulo que identifica qual carga de trabalho do gateway recebe o filtro Envoy.
--
servicesLista de nomes de serviço gRPC totalmente qualificados (
<package>.<service>) para transcodificar.--
printOptions.addWhitespaceFormata respostas JSON com indentação para melhor legibilidade.
falseprintOptions.alwaysPrintEnumsAsIntsExibe valores de enumeração como inteiros em vez de nomes.
falseprintOptions.alwaysPrintPrimitiveFieldsInclui campos com valores padrão (por exemplo, um
int32definido como0) na resposta JSON. Quandofalse, esses campos são omitidos.falseprintOptions.preserveProtoFieldNamesUsa os nomes originais dos campos proto na saída JSON em vez de converter para camelCase.
falsePara a referência completa de campos, consulte Descrições dos campos do ASMGrpcJsonTranscoder.
-
Aplique o recurso:
kubectl apply -f grpcjsontranscoder-helloworld.yaml
Verifique a transcodificação
Após aplicar o recurso ASMGrpcJsonTranscoder, o ingress gateway passa a aceitar requisições HTTP/JSON e a transcodificá-las para gRPC.
-
Obtenha o endereço IP do ingress gateway:
kubectl -n istio-system get svc istio-ingressgateway \ -o jsonpath='{.status.loadBalancer.ingress[0].ip}' -
Envie uma requisição de teste para a porta 8080:
curl http://<ingress-gateway-ip>:8080/sayHello/MarkSubstitua
<ingress-gateway-ip>pelo endereço IP obtido na etapa 1. -
Verifique a resposta. Uma resposta bem-sucedida tem o seguinte formato:
{ "message": "Hello, Mark! I'm from grpc-helloworld-py-v1-79b5dc9654-cg4dq!" }Uma resposta JSON do serviço gRPC de backend confirma que a transcodificação de HTTP para gRPC está funcionando.
Próximos passos
Descrições dos campos do ASMGrpcJsonTranscoder: referência completa dos campos da CRD.
Usar um ingress gateway para acessar um serviço gRPC em uma instância do ASM: configure o acesso direto via gRPC sem transcodificação HTTP.