An Interest In:
Web News this Week
- March 22, 2024
- March 21, 2024
- March 20, 2024
- March 19, 2024
- March 18, 2024
- March 17, 2024
- March 16, 2024
O que gRPC - Como usar os Protocol Buffers | Parte 2
Autor: Rodrigo G. Tavares
Veja a Parte 1: O que gRPC - Seus componentes RPC e HTTP2
Protocol Buffers ou para os ntimos Protobuf, uma linguagem neutra criada para permitir a integrao entre linguagens de programao, tambm usado como IDL pelo sistema gRPC.
Veremos nesse artigo o que so os Protocol Buffers, como eles funcionam e como eles se integram com o sistema gRPC.
Introduo
Quando falamos de integrao entre linguagens, estamos trazendo o conceito de interoperabilidade, ou seja, a capacidade das aplicaes e sistemas se comunicarem de maneira simples e fcil e exatamente esse o papel dos Protocol Buffers.
O que so os Protocol Buffers
Basicamente so uma linguagem neutra e de plataforma neutra, usada para definio de tipos de dados e funes, muito parecido com o formato JSON, porm menor e mais rpido.
Como vimos no artigo anterior, ele usado como IDL, linguagem para definio de interfaces, no sistema gRPC.
Por que eu preciso de uma linguagem neutra?
Uma linguagem neutra uma linguagem simples, usada pra fazer a definio das interfaces e tipos usado nas integraes.
A partir dessa interface, cada linguagem que queira fazer uma integrao deve interpretar o cdigo escrito na IDL, gerando funes e tipos nos padres da sua linguagem.
Essas interfaces geradas so chamadas de stubs e so usadas tanto pelo provedor de servios, quanto pelo consumidor.
O lado provedor usar as interfaces para efetivamente implementar as regras daquele servio, enquanto o consumidor, como o prprio nome diz, vai us-las pra consumir, ou seja, acessar os servios.
E exatamente esse o papel dos protocol buffers.
Estrutura dos Protocol Buffers
Precisamos de ateno nos padres e convenes de formatao do arquivo proto.
Mas por que isso importante?
Usar o formato correto faz com que o processo de gerao dos stubs siga as convenes de cada linguagens de destino.
Em resumo, seguindo o padro dos protocol buffers, far com que o cdigo gerado tambm esteja no padro da linguagem.
Configuraes
Ao criar o arquivo proto buffer, por conveno o nome do arquivo deve ser todo minsculo com a extenso .proto.
Exemplo:
- pessoa.proto
- pessoafisica.proto
- pessoajuridica.proto
Sintaxe
Uma vez criado o arquivo, devemos atribuir a verso da sintaxe, que pode ser proto2 ou proto3.
syntax = "proto3";
Desse ponto em diante focaremos na verso de sintaxe proto3, que a mais recente, para mais detalhes da verso proto2, h um link para a documentao nas referncias do artigo.
Pacote
Agora precisamos definir o pacote, essa uma instruo opcional usada pra compor o nome da mensagem, essa configurao deixa o nome nico e evitando conflitos com outros tipos de nome semelhante, ou seja, podemos ter tipos de nomes iguais, desde de que estejam em pacotes diferentes.
package expertostech;
A instruo package em Java, go e csharp usada pra compor o cdigo gerado, no caso do csharp o valor atribudo ao namespace, j no Go e no Java atribudo em uma propriedade de mesmo nome.
Importao
Depois temos a rea de importao, onde voc pode fazer referncia pra outros tipos, como o caso da definio de data hora que precisa ser importado. Voc tambm pode importar seus prprios tipos aqui.
import "google/protobuf/timestamp.proto";
Opes adicionais
Vamos agora para as configuraes especficas para cada linguagem.
Para o Java, as configuraes so:
java_multiple_files
, se verdadeiro, indica que as classes sero geradas em arquivos separados.java_outer_classname
, o nome da classe de gerao.
option java_multiple_files = true;option java_outer_classname = "PessoaProtos";
Se voc quiser organizar seus arquivos proto em pacotes (ou namespace) diferentes das suas classes, voc pode usar as seguintes configuraes:
java_package
, para o Java;go_package
, para o Go;csharp_namespace
, para o C#.
Essas trs configuraes sobrescrevem o valor do pacote, package, nproto, alterando os valores para gerao das classes.
option java_package = "expertostech.tutorial.grpc";option go_package = "expertostech/tutorial/grpc";option csharp_namespace = "ExpertosTech.Tutorial.Grpc";
Definio de tipos
Uma curiosidade, que os tipos nos proto buffers so chamados de mensagem, justamente por que esses tipos declarados so usados como mensagem de envio e recebimento nas suas integraes entre sistemas.
Mensagem
Iniciamos a declarao cada tipo com a palavra chave message, seguido do nome no padro CamelCase.
message Pessoa {}
importante saber que podemos declarar vrias mensagens em um arquivo proto.
message Pessoa {}message Usuario {}
Atributos
Agora vamos declarar os atributos da mensagem.
Cada atributo comea com o tipo, seguido do nome e ao fim um cdigo de identificao nico.
message Pessoa { string documento_pessoal = 1;}
Esse cdigo deve ser nico na mensagem e no no arquivo proto, isso quer dizer que voc pode ter vrios identificadores de atributo com o nmero 1, por exemplo, desde que eles estejam em mensagens diferentes.
message Pessoa { string documento_pessoal = 1;}message Usuario { string login = 1;}
Essa identificao deve ser feita a partir do nmero 1 e pode chegar at 536.870.911, ou (2^29)-1.
Tenho minhas dvidas se voc vai precisar chegar to longe, mas importante dizer que os nmeros entre 19.000 19.999 so reservados para a identificao dos atributos do framework, isso quer dizer que se voc us-los, a gerao dos stubs apresentar erro.
Nos atributos usamos como conveno de nome, letras minsculas separando cada palavra com um underscore.
message Pessoa { string documento_pessoal = 1; string nome = 2;}
Tipos de dados
Na tabela abaixo podemos ver os principais tipos para declarao de atributos e quais so os seus correspondentes nas principais linguagens. Caso queira ver a lista completa, h um link para a documentao nas referncias do artigo.
.proto Type | C++ Type | Java/Kotlin Type | C# Type | Go Type |
---|---|---|---|---|
string | string | String | string | string |
int32 | int32 | int | int | int |
float | float | float | float | float64 |
double | double | double | double | float32 |
bool | bool | boolean | bool | bool |
Alm dos tipos de dados da linguagem, voc tambm pode usar como tipos nos seus atributos suas prprias mensagens, ou seja, voc pode por exemplo criar uma mensagem Cidade
e us-la como referncia dentro da mensagem Endereco
.
message Endereco { string logradouro = 1; string numero = 2; string bairro = 3; Cidade cidade = 4;}message Cidade { string nome = 1; int32 ddd = 2;}
importante ressaltar que no caso do tipo utilizado estar em outro arquivo proto, necessrio import-lo na seo import
, como pode ser visto no exemplo abaixo.
// ...import "endereco.proto";// ...message Pessoa { string documento_pessoal = 1; string nome = 2; Endereco endereco = 3;}
Listas de valores
Um recurso muito utilizado nas integraes so as listas, e temos dois tipos de listas nos protocol buffers:
Listas simples
Para declarar uma lista usamos a palavra chave repeated
, seguida pelo tipo do campo e o nome da lista.
Por conveno, uma vez que as listas listas possuem diversos itens, elas so sempre nomeadas no plural.
message Pessoa { repeated Endereco enderecos = 3;}
Listas chave e valor
Outra lista que temos disponvel a de chave e valor, chamada de map
, nesse tipo de lista podemos definir um tipo de dado para chave e outro tipo de dado para valor, lembrando que tanto na chave quanto no valor podemos usar tanto os tipos da linguagem, quanto nossos prprios tipos.
message Pessoa { map<string, google.protobuf.Timestamp> atualizacoes = 4;}
Enumeraes
Fechando os principais tipos da linguagem, tambm temos um conjunto de valores fixos chamados de enum
.
Os enums tm a estrutura semelhante a de uma mensagem, porm, ao invs de atributos, h uma lista fixa de valores.
Pra declarar uma enumerao usamos a palavra chave enum
seguida do nome no padro CamelCase.
Para a lista de valores usamos as letras todas maisculas separando as palavras por um underscore.
Os itens do enum
tambm precisam ser numerados, s que diferente dos atributos da mensagem, a lista de valores do enum deve iniciar no nmero zero.
enum TipoPessoa { NAO_DEFINIDA = 0; FISICA = 1; JURIDICA = 2;}
Servios
Fechamos a definio dos tipos, agora precisamos definir as nossas funes.
Isso muito simples, usamos a palavra chave service
, seguida do nome do servio no padro CamelCase.
service PessoaServico {}
Para declararmos uma funo dentro do seu servio, iniciamos com a palavra chave rpc
, seguida pelo o nome da funcionalidade no padro CamelCase, o parmetro de entrada entre parnteses, seguido da palavra chave returns
com a mensagem de retorno da funo tambm entre parnteses.
service PessoaServico { rpc PessoaPorDocumento(Pessoa) returns (Pessoa) {}}
Podemos declarar vrias funes dentro de um mesmo servio e obrigatoriamente todas elas precisam de uma mensagem como parmetro de entrada e uma outra como parmetro de sada, no podemos ter funes sem entrada ou sada, e os parmetros devem obrigatoriamente ser mensagens e no tipos simples.
service PessoaServico { rpc PessoaPorDocumento(Pessoa) returns (Pessoa) {} rpc PessoaPorNome(Pessoa) returns (Pessoa) {}}
Vejamos abaixo o cdigo completo dos protocol buffers usados at aqui como exemplos.
Arquivo: endereco.proto
syntax = "proto3";package expertostech;option java_multiple_files = true;option java_outer_classname = "EnderecoProtos";option java_package = "expertostech.tutorial.grpc";option go_package = "expertostech/tutorial/grpc";option csharp_namespace = "ExpertosTech.Tutorial.Grpc";message Endereco { string logradouro = 1; string numero = 2; string bairro = 3; Cidade cidade = 4;}message Cidade { string nome = 1; int32 ddd = 2;}
Arquivo: pessoa.proto
syntax = "proto3";package expertostech;import "google/protobuf/timestamp.proto";import "endereco.proto";option java_multiple_files = true;option java_outer_classname = "PessoaProtos";option java_package = "expertostech.tutorial.grpc";option go_package = "expertostech/tutorial/grpc";option csharp_namespace = "ExpertosTech.Tutorial.Grpc";service PessoaServico { rpc PessoaPorDocumento(Pessoa) returns (Pessoa) {} rpc PessoaPorNome(Pessoa) returns (Pessoa) {}}message Pessoa { string documento_pessoal = 1; string nome = 2; repeated Endereco enderecos = 3; map<string, google.protobuf.Timestamp> atualizacoes = 4; TipoPessoa tipo_pessoa = 5;}enum TipoPessoa { NAO_DEFINIDA = 0; FISICA = 1; JURIDICA = 2;}message Usuario { string login = 1; string senha = 2;}
Gerando os stubs com Java
Para testar a gerao veja o projeto completo no github:
github/expertos-tech/protocol-buffer
Veja abaixo a estrutura do projeto e arquivo pom.xml
.
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>expertostech</groupId> <artifactId>stub-gen</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-stub</artifactId> <version>1.45.1</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-protobuf</artifactId> <version>1.45.1</version> </dependency> <dependency> <groupId>jakarta.annotation</groupId> <artifactId>jakarta.annotation-api</artifactId> <version>1.3.5</version> <optional>true</optional> </dependency> </dependencies> <build> <extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.4.1.Final</version> </extension> </extensions> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protocArtifact>com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}</protocArtifact> <pluginId>grpc-java</pluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.4.0:exe:${os.detected.classifier}</pluginArtifact> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins> </build></project>
O que vem a seguir?
Fechamos a definio dos protocol buffers, que a parte central do sistema gRPC.
No prximo artigo, ltima parte dessa srie, entraremos na parte prtica de tudo que vimos at aqui, a implementao passo a passo de um servio gRPC com Java, usando os protocol buffers.
E se voc chegou at aqui, deixe o seu gostei no artigo e j aproveita pra seguir o canal ExpertosTech em todas redes sociais:
https://linktr.ee/expertostech
Referencias:
Original Link: https://dev.to/expertostech/o-que-e-grpc-como-usar-os-protocol-buffers-parte-2-mk3
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To