Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
April 26, 2022 04:01 pm GMT

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.

Image description

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 TypeC++ TypeJava/Kotlin TypeC# TypeGo Type
stringstringStringstringstring
int32int32intintint
floatfloatfloatfloatfloat64
doubledoubledoubledoublefloat32
boolboolbooleanboolbool

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.

Image description

<?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

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To