1. Introdução
Neste codelab, você vai usar o gRPC-Python para criar um cliente e um servidor que formam a base de um aplicativo de mapeamento de rotas escrito em Python.
Ao final do tutorial, você terá um cliente que se conecta a um servidor remoto usando o gRPC para receber o nome ou o endereço postal do que está localizado em coordenadas específicas em um mapa. Um aplicativo completo pode usar esse design cliente-servidor para enumerar ou resumir pontos de interesse ao longo de um trajeto.
O serviço é definido em um arquivo Protocol Buffers, que será usado para gerar código boilerplate para o cliente e o servidor, permitindo que eles se comuniquem entre si e economizando tempo e esforço na implementação dessa funcionalidade.
Esse código gerado cuida não apenas das complexidades da comunicação entre o servidor e o cliente, mas também da serialização e desserialização de dados.
O que você vai aprender
- Como usar buffers de protocolo para definir uma API de serviço.
- Como criar um cliente e um servidor baseados em gRPC com uma definição de buffers de protocolo usando a geração automática de código.
- Entendimento da comunicação cliente-servidor com gRPC.
Este codelab é destinado a desenvolvedores Python que não conhecem o gRPC ou querem relembrar o assunto, ou a qualquer pessoa interessada em criar sistemas distribuídos. Não é necessário ter experiência com gRPC.
2. Antes de começar
O que é necessário
- Python 3.9 ou mais recente. Recomendamos o Python 3.13. Para instruções de instalação específicas da plataforma, consulte Configuração e uso do Python. Se preferir, instale um Python não sistêmico usando ferramentas como uv ou pyenv.
- pip para instalar pacotes Python.
- venv para criar ambientes virtuais em Python.
Os pacotes ensurepip
e venv
fazem parte da biblioteca padrão do Python e geralmente estão disponíveis por padrão.
No entanto, algumas distribuições baseadas em Debian (incluindo o Ubuntu) optam por excluí-los ao redistribuir o Python. Para instalar os pacotes, execute:
sudo apt install python3-pip python3-venv
Acessar o código
Para facilitar o aprendizado, este codelab oferece um scaffold de código-fonte pré-criado para ajudar você a começar. As etapas a seguir vão orientar você na conclusão do aplicativo, incluindo a geração de código gRPC usando o plug-in do compilador de buffer de protocolo grpc_tools.protoc
.
grpc-codelabs
O código-fonte do scaffold para este codelab está disponível no diretório codelabs/grpc-python-getting-started/start_here. Se preferir não implementar o código por conta própria, o código-fonte concluído está disponível no diretório completed
.
Primeiro, crie o diretório de trabalho do codelab e use cd para acessar ele:
mkdir grpc-python-getting-started && cd grpc-python-getting-started
Faça o download e extraia o codelab:
curl -sL https://github.com/grpc-ecosystem/grpc-codelabs/archive/refs/heads/v1.tar.gz \
| tar xvz --strip-components=4 \
grpc-codelabs-1/codelabs/grpc-python-getting-started/start_here
Como alternativa, baixe o arquivo .zip que contém apenas o diretório do codelab e descompacte-o manualmente.
3. Definir o serviço
A primeira etapa é definir o serviço gRPC do aplicativo, o método RPC e os tipos de mensagens de solicitação e resposta usando a linguagem de definição de interface Protocol Buffers. Seu serviço vai oferecer:
- Um método RPC chamado
GetFeature
que o servidor implementa e o cliente chama. - Os tipos de mensagem
Point
eFeature
são estruturas de dados trocadas entre o cliente e o servidor ao usar o métodoGetFeature
. O cliente fornece coordenadas do mapa como umPoint
na solicitaçãoGetFeature
ao servidor, e o servidor responde com umFeature
correspondente que descreve o que está localizado nessas coordenadas.
Esse método RPC e os tipos de mensagem dele serão definidos no arquivo protos/route_guide.proto
do código-fonte fornecido.
Os buffers de protocolo são conhecidos como protobuf. Para mais informações sobre a terminologia do gRPC, consulte Conceitos principais, arquitetura e ciclo de vida do gRPC.
Tipos de mensagem
No arquivo protos/route_guide.proto
do código-fonte, primeiro defina o tipo de mensagem Point
. Um Point
representa um par de coordenadas de latitude e longitude em um mapa. Neste codelab, use números inteiros para as coordenadas:
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
Os números 1
e 2
são IDs exclusivos para cada um dos campos na estrutura message
.
Em seguida, defina o tipo de mensagem Feature
. Um Feature
usa um campo string
para o nome ou endereço postal de algo em um local especificado por um Point
:
message Feature {
// The name or address of the feature.
string name = 1;
// The point where the feature is located.
Point location = 2;
}
Método de serviço
O arquivo route_guide.proto
tem uma estrutura service
chamada RouteGuide
que define um ou mais métodos fornecidos pelo serviço do aplicativo.
Adicione o método rpc
GetFeature
à definição RouteGuide
. Como explicado anteriormente, esse método vai pesquisar o nome ou endereço de um local em um determinado conjunto de coordenadas. Portanto, faça com que GetFeature
retorne um Feature
para um determinado Point
:
service RouteGuide {
// Definition of the service goes here
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
}
Esse é um método RPC unário: um RPC simples em que o cliente envia uma solicitação ao servidor e aguarda uma resposta, assim como uma chamada de função local.
4. Gerar o código do cliente e do servidor
Em seguida, gere o código gRPC boilerplate para o cliente e o servidor do arquivo .proto
usando o compilador de buffer de protocolo.
Para a geração de código Python do gRPC, criamos o grpcio-tools. Ela inclui:
- O compilador protoc comum que gera código Python com base em definições
message
. - Plug-in protobuf do gRPC que gera código Python (stubs de cliente e servidor) das definições
service
.
Vamos instalar o pacote Python grpcio-tools
usando pip. Vamos criar um novo ambiente virtual do Python (venv) para isolar as dependências do projeto dos pacotes do sistema:
python3 -m venv --upgrade-deps .venv
Para ativar o ambiente virtual no shell bash/zsh:
source .venv/bin/activate
Para Windows e shells não padrão, consulte a tabela em https://docs.python.org/3/library/venv.html#how-venvs-work.
Em seguida, instale o grpcio-tools (isso também instala o pacote grpcio):
pip install grpcio-tools
Use o comando a seguir para gerar o código boilerplate do Python:
python -m grpc_tools.protoc --proto_path=./protos \
--python_out=. --pyi_out=. --grpc_python_out=. \
./protos/route_guide.proto
Isso vai gerar os seguintes arquivos para as interfaces definidas em route_guide.proto
:
route_guide_pb2.py
contém o código que cria classes dinamicamente geradas das definiçõesmessage
.route_guide_pb2.pyi
é um "arquivo stub" ou "arquivo de dica de tipo" gerado das definiçõesmessage
. Ele contém apenas as assinaturas, sem implementação. Os arquivos stub podem ser usados por IDEs para oferecer melhor preenchimento automático e detecção de erros.- O
route_guide_pb2_grpc.py
é gerado com base nas definiçõesservice
e contém classes e funções específicas do gRPC.
O código específico do gRPC contém:
RouteGuideStub
, que pode ser usado por um cliente gRPC para invocar RPCs do RouteGuide.RouteGuideServicer
, que define a interface para implementações do serviçoRouteGuide
.- Função
add_RouteGuideServicer_to_server
usada para registrar umRouteGuideServicer
em um servidor gRPC.
5. Criar o serviço
Primeiro, vamos ver como criar um servidor RouteGuide
. A criação e a execução de um servidor RouteGuide
são divididas em dois itens de trabalho:
- Implementar a interface do serviço gerada da nossa definição de serviço com funções que realizam o "trabalho" real do serviço.
- Executar um servidor gRPC em uma porta específica para detectar solicitações de clientes e transmitir respostas.
O servidor RouteGuide
inicial pode ser encontrado em start_here/route_guide_server.py
.
Implementar o RouteGuide
route_guide_server.py
tem uma classe RouteGuideServicer
que é subclasse da classe gerada route_guide_pb2_grpc.RouteGuideServicer
:
# RouteGuideServicer provides an implementation
# of the methods of the RouteGuide service.
class RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer):
RouteGuideServicer
implementa todos os métodos de serviço RouteGuide
.
Vamos analisar uma implementação simples de RPC em detalhes. O método GetFeature
recebe um Point
do cliente e retorna as informações de recurso correspondentes do banco de dados em Feature
.
def GetFeature(self, request, context):
feature = get_feature(self.db, request)
if feature is None:
return route_guide_pb2.Feature(name="", location=request)
else:
return feature
O método recebe uma solicitação route_guide_pb2.Point
para a RPC e um objeto grpc.ServicerContext
que fornece informações específicas da RPC, como limites de tempo limite. Ele retorna uma resposta route_guide_pb2.Feature
.
Como iniciar o servidor
Depois de implementar todos os métodos RouteGuide
, a próxima etapa é iniciar um servidor gRPC para que os clientes possam usar seu serviço:
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
route_guide_pb2_grpc.add_RouteGuideServicer_to_server(
RouteGuideServicer(),
server,
)
listen_addr = "localhost:50051"
server.add_insecure_port(listen_addr)
print(f"Starting server on {listen_addr}")
server.start()
server.wait_for_termination()
O método do servidor start()
não é bloqueador. Um novo thread será instanciado para processar solicitações. A linha de execução que chama server.start()
geralmente não tem outro trabalho a fazer nesse meio tempo. Nesse caso, chame server.wait_for_termination()
para bloquear corretamente a linha de execução da chamada até que o servidor seja encerrado.
6. Criar o cliente
Nesta seção, vamos criar um cliente para nosso serviço RouteGuide
. É possível conferir o código do cliente inicial em start_here/route_guide_client.py
.
Criar um stub
Para chamar métodos de serviço, primeiro precisamos criar um stub.
Vamos instanciar a classe RouteGuideStub
do módulo route_guide_pb2_grpc
, gerada do nosso .proto
dentro do arquivo route_guide_client.py
.
channel = grpc.insecure_channel("localhost:50051")
stub = route_guide_pb2_grpc.RouteGuideStub(channel)
Como chamar métodos de serviço
Para métodos RPC que retornam uma única resposta, conhecidos como métodos response-unary, o gRPC Python é compatível com semântica de fluxo de controle síncrona (bloqueio) e assíncrona (não bloqueio).
RPC simples
Primeiro, vamos definir um Point
para chamar o serviço. Isso é tão simples quanto instanciar um objeto do pacote route_guide_pb2
com algumas propriedades:
point = route_guide_pb2.Point(latitude=412346009, longitude=-744026814)
Uma chamada síncrona para o RPC simples GetFeature
é quase tão direta quanto chamar um método local. A chamada de RPC aguarda a resposta do servidor e retorna uma resposta ou gera uma exceção. Podemos chamar o método e ver a resposta assim:
feature = stub.GetFeature(point)
print(feature)
É possível inspecionar os campos do objeto "Feature" e gerar o resultado da solicitação:
if feature.name:
print(f"Feature called '{feature.name}' at {format_point(feature.location)}")
else:
print(f"Found no feature at at {format_point(feature.location)}")
7. Faça um teste
Execute o servidor:
python route_guide_server.py
Em outro terminal, ative o ambiente virtual novamente e execute o cliente:
python route_guide_client.py
Você vai ver uma saída como esta, com carimbos de data/hora omitidos para maior clareza:
name: "16 Old Brook Lane, Warwick, NY 10990, USA" location { latitude: 412346009 longitude: -744026814 } Feature called '16 Old Brook Lane, Warwick, NY 10990, USA' at latitude: 412346009, longitude: -744026814
8. A seguir
- Saiba como o gRPC funciona em Introdução ao gRPC e Conceitos principais.
- Siga as etapas do tutorial de noções básicas.
- Confira a referência da API Python.