- Remote Protocol Call
- Padrão de comunicacao para chamar funcao ou metodo
- Complexidade de rede é abstraida (sem abrir ‘socket’, etc)
- gRPC (Google, mas na vdd cada release tem um significado como garcia, good, green etc)
- substituir o Stubby por uma implementacao utilizando HTTP/2
- CNCF estabelece principios para projeto gRPC
- Nao funciona com HTTP/1.1
- HTTP/2
- Somente formato binario (formato menor)
- Multiplexacao
- Unica comunicacao pode-se enviar varios requestes em paraleleto, ao contratio da 1.1
- Compressao header com HPACK (enviar apenas cabeçalhos que mudaram)
- HTTP/1.1 tem pipelining, mas é uma req por ordem
- Server Push
- Servidor envia para o cliente mais coisas do que ele pediu (eg ja manda arquivos CSS e JS)
- Serializacao padrao usado pelo gRPC
- Independente do gRPC, mas é o mais utilizado
- Tipadas e estruturados
- Compacto, cross-lang, otimizado e compacto
- Fornece IDL (interface Definition Language)
- Mensagens, servicos e arquivo
.proto.
- Mensagens, servicos e arquivo
- Diagrama:
- Crie .proto data structure -> Gere codigo usando protoc compiler -> Compile PB no seu projeto
- PB classes será usado para serdes
- Parecido com Avro
- Contratos desatualizados n geram erros, mas campo sao ignorados
eg golang
syntax = "proto3";
option go_package = "github.com/Rafaellinos/grpc/helloworld";
package helloworld;
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}On Mac M1, run these commands:
brew install protoc-gen-goinstall go generator and add to your ~/.zshrcexport PATH="$PATH:$(go env GOPATH)/bin"
cd helloworld && protoc --go_out=. --go_opt=module=github.com/Rafaellinos/grpc/helloworld --go-grpc_out=. --go-grpc_opt=module=github.com/Rafaellinos/grpc/helloworld ./proto/helloworld.proto-
float
-
int32 (para valores negativos, use sint32)
-
int64 (para valores negativos, use sint64)
-
uint32 (sem sinal)
-
uint64 (sem final)
-
sint32
-
sint64
-
fixed32 (valores fixos, bom para valores grandes 2^28)
-
fixed64 (valores fixos, bom para valores grande 2^58)
-
sfixes32 (sempre 4 bytes)
-
sfixed64 (sempre 8 bytes)
-
bool
-
string (utf8 ou ASCI, n pode ser maior que 2ˆ32)
-
bytes (n pode ser maior que 2^32)
-
Valores default: numerico = 0, bytes = vazio, string = vazio, bool = false
-
Quando o campo é valor default, n é enviado na msg, mesmo que tenha sido setado.
- campos unicos (singular)
- implicit
- optional
- Colecoes: repeated
- Mapas: maps
syntax = "proto3";
message UserDetails {
string name = 1;
uint32 age = 2;
optional bool is_active = 3;
}Quando campos esta com optional, no golang será um ponteiro (*isActive) entao é possivel verificar se é nil
Campos do tipo Message (outra referencia) é um ponteiro por default
É possível "decodar" o hexadecimal para obter os detalhes da mensagem.
Para gerar a mensagem em formato binario, usa o comando abaixo:
protoc --encode=helloworld.GreetRequest helloworld.proto < request.txt > wire_format.binArquivo protobuf text format
type: 0
users: [{
name: "Rafael"
age: 35
},
{
name: "Yasmin"
age: 27
is_active: true
}]
- Wire format (tipos de arquivo binarios)
- VARINT (int32, int64, sint64, bool, enum)
- I64 (fixed64, sfixed64, double)
- LEN (string, bytes, embeedded msgs, packed repeated fields)
- I32 (fixed32, sfixed32, double)
- Estrutura
- field number | type (tipo do campo) | payload
- Nao é possivel saber o nome do campo pelo wire format, apenas o indice (field number)
- Nao é possivel saber com exatidao o tipo do campo, apenas com o contrato (.proto)
- Field numbers (ids/index de campos, como
string name = 1)- Nao podem se repetir dentro da mesma msg
- 19_000 a 19_999 eh reservado
- é possivel reservar numeros
- Quando adicionar novo campo, boa pratica será usar
optional - !warning cuidado ao mudar o nome e tipo do campo e manter o mesmo ID, pois o servidor vai considerar como mesmo campo
- use
reserved <ID>para reservar campos, util para evitar erros quando removemos campos
- unica mensagem, mais simples
- server streaming (comunicacao constante, mantem comunicacao aberta)
- client streaming
- bidirectional streaming
- must have the plubin
protobuf-maven-plugin - run
mvn generate-sourcesto generate classes based on .proto file ⚠️ Remember to add target/generated-sources/protobuf/grpc-java and /java in /target as source root
eg em java:
syntax = "proto3";
option java_package = "br.com.rafaellino.stockmarket";
option java_multiple_files = true;
package stock_market;
service StockPrice {
rpc GetStockPrice (StockRequest) returns (StockResponse);
}
message StockRequest {
string symbol = 1;
}
message StockResponse {
string symbol = 1;
double price = 2;
int64 timestamp = 3;
}Entre no directory stockmarket_consumer
python -m venv .venv # crie o virtual environmentsource .venv/bin/activate # ative o virtual environmentpip install -r requirements.txt # instale dependenciaspython main.py # com a aplicacao stockmarket rodando, execute o main.pyPara gerar o arquivo com base no proto file:
python -m grpc_tools.protoc -I . --python_out=. --grpc_python_out=. stock_market.protogo mod downloaddownload dependencies, nao modifica go.mod ou go.sumgo mod tidylimpa e atualiza go.mod e go.sum de acordo com dependencias- go.mod = arquivo que define nome do modulo, versao e dependencias
- go.sum = arquivo que armazena checksums de dependencias baixadas
cd helloworld && go build -o bin/server ./serverbuildar o projeto
Tempo maximo que o cliente espera pela resposta do servidor. Quando o client chega ao deadline, recebe o erro: DEADLINE_EXCEEDED
- Uma unica mensagem, request e response, parecido com HTTP/REST
e.g.:
syntax = "proto3";
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
rpc SayHelloStream (HelloRequest) returns (stream HelloReply);
}- chave
streamespecifica o tipo