gRPC: o que é e como utilizá-lo na sua próxima aplicação

Nos últimos anos, surgiu um novo conceito de comunicação para microsserviços: o gRPC. Conhecida por ser uma estrutura moderna de código aberto e alto desempenho, esse tipo de protocolo foi criado pelo Google e permite a comunicação entre diferentes sistemas via conexão de rede, com base em HTTP/2.

Neste artigo, conheça esse novo protocolo e o motivo dele ser usado como a nova geração de comunicação entre microsserviços. Além disso, veja um exemplo prático de gRPC utilizando o framework do Beagle.  

Você vai ver neste artigo:

  • gRPC: o que é, afinal?
  • gRPC vs Rest
  • Alguns cenários uso de gRPC
  • Aplicação na prática: Beagle com gRPC
  • Vamos ao tutorial de Beagle com gRPC

gRPC: o que é, afinal?

Como dissemos anteriormente, o gRPC é uma estrutura de código aberto e alto desempenho criada pelo Google. O gRPC segue amplamente a semântica HTTP sobre HTTP/2 e, assim permite que você use o streaming full-duplex, possibilitando a comunicação entre diferentes sistemas via conexão de rede. 

Com isso, um ponto de grande impacto é o ganho de performance ao trafegar um payload extensivo, visto que, no gRPC a comunicação é feita em binário, o que traz uma melhora enorme na performance, que pode ser até 7 vezes mais rápida na resposta de dados e 10 vezes no envio. Isso se deve principalmente ao empacotamento compacto dos proto buffers e ao uso de HTTP/2 pelo gRPC.

A proposta do gRPC é que o cliente interaja com o servidor por meio de chamadas de funções simples, ou seja, de interfaces de códigos geradas automaticamente pela própria aplicação do gRPC. Isso significa que você precisa apenas implementar sua lógica de programação, o que facilita muito a adoção desse recurso.

Com isso, você tem algumas vantagens na sua arquitetura de microsserviços, como, por exemplo:

  • Fácil o contrato entre cliente e servidor;
  • Melhor o desempenho dos serviços;
  • Features nativas do HTTP/2, como streaming de dados, load balance, monitoramento etc.

Em resumo, é como se você declarasse funções e classes em um back-end e pudesse acessá-los no front-end graças ao arquivo de contrato que contém suas interfaces (serviços e DTOs).

gRPC vs Rest

O que mais diverge do REST – o protocolo de comunicação mais comum em arquitetura de microsserviços – é que, com gRPC, são usados caminhos estáticos para um melhor desempenho durante o despacho de chamadas, já que a análise de path params, query params e payload adiciona latência e complexidade à comunicação entre serviços. 

Além disso, existe um conjunto de erros que são mais diretamente aplicáveis ​​a casos de uso de API do que os códigos de status HTTP convencionalmente utilizados no REST.

FuncionalidadegRPCRest
ProtocolHTTP/2(fast)HTTP/1.1(slow)
PayloadProtobuf (binary/ ,small)JSON (text, large)
API ContractStrict, required (.proto)Loose optional (OpenAPI)
Code generationBuilt-in (protoc)Third-party tools (Swagger)
SecurityTSL/SSLTLS/SSL
StreamingBidirectional streamingClient ->server request only
Browser supportLimited (require gRPC-web)Yes
Fonte.

Alguns cenários uso de gRPC

  • Sistemas multilíngues: com seu suporte de geração de código nativo para uma ampla gama de linguagens de desenvolvimento, o gRPC é excelente para gerenciar conexões em um ambiente poliglota. 
  • Streaming em tempo real: quando a comunicação em tempo real é um requisito, a capacidade do gRPC de gerenciar o streaming bidirecional permite que seu sistema envie e receba mensagens em tempo real sem esperar pela comunicação de resposta do cliente. 
  • Redes de baixa largura de banda e de baixa potência: o uso de mensagens Protobuf serializadas pelo gRPC permite mensagens leves, o que contribui para maior eficiência e velocidade em redes de baixa potência e de largura de banda restritas (especialmente quando comparadas a JSON). A IoT seria um exemplo desse tipo de rede que poderia se beneficiar das APIs gRPC.

Aplicação na prática: Beagle com gRPC 

Neste exemplo, nós te mostraremos como implantar o protocolo gRPC utilizando o framework do Beagle, a partir de uma demonstração bastante simples de um “hello world” envolvendo um cliente e um servidor.

Para quem não conhece, o Beagle é nosso framework open source de desenvolvimento cross-platform que é pautado no paradigma de implementação Server Driven UI

Até então, nós só oferecíamos suporte para serviços com protocolo REST, trafegando dados apenas via JSON. Mas para solucionarmos esse impasse, criamos uma biblioteca que mapeia os contratos em JSON do Beagle e os traduz em binários para trafegá-los via proto buffers. 

Com isso, é possível reutilizar o código de projetos Beagle feitos em REST, em projetos gRPC, adicionando poucas linhas de código.

A lib do Beagle gRPC está disponível para as plataformas Android, iOS, web e back-end. Ela oferece suporte nativo:

Ao mobile, com Kotlin e Swift.

Já na web, podemos usá-la com Angular e React.

Por fim, no back-end ela suporta Spring Boot e Micronaut, nas linguagens Java e Kotlin.

Vamos ao tutorial de Beagle com gRPC 

  • No lado do servidor: sua API deve ser criada usando a lib gRPC, disponibilizada pelo Spring Boot ou Micronaut. Caso você prefira, também pode subir seu próprio servidor manualmente usando apenas o framework do gRPC direto.

    Feito isso, é possível implementar um serviço disponibilizado pela nossa lib. A partir daí, ela devolve suas telas e componentes que foram criados com Beagle na sua aplicação back-end, totalmente serializados como um objeto gRPC, em vez de devolver um JSON tradicional, que é disponibilizado para os clientes em um formato conhecido como protobuf (protocol buffer).

Segue abaixo, exemplos de duas telas feitas declarativamente utilizando Beagle no back-end:

  • Home screen:
import br.com.zup.beagle.widget.layout.Container
import br.com.zup.beagle.widget.layout.Screen
import br.com.zup.beagle.widget.layout.ScreenBuilder
import br.com.zup.beagle.widget.ui.Text

class HomeScreen(private val parameters: String) : ScreenBuilder {
    override fun build() = Screen(
        child = Container(
            children = listOf(
                Text("Hello. This is a $parameters!")
            )
        )
    )
}
  • Splash screen:
import br.com.zup.beagle.core.CornerRadius
import br.com.zup.beagle.ext.setStyle
import br.com.zup.beagle.widget.action.Navigate
import br.com.zup.beagle.widget.action.Route
import br.com.zup.beagle.widget.core.EdgeValue
import br.com.zup.beagle.widget.core.UnitValue
import br.com.zup.beagle.widget.layout.Container
import br.com.zup.beagle.widget.layout.Screen
import br.com.zup.beagle.widget.layout.ScreenBuilder
import br.com.zup.beagle.widget.ui.Button

class SplashScreen() : ScreenBuilder {
    override fun build() = Screen(
        child = Container(
            children = listOf(
                Button(
                    text = "Button with Style",
                    onPress = listOf(Navigate.PushView(Route.Remote("text", true)))
                ).setStyle { margin = EdgeValue(UnitValue(15.0)) },
                Button(
                    text = "Button with Appearance and Style",
                    onPress = listOf(Navigate.PushView(Route.Remote("text", true)))
                ).setStyle {
                    backgroundColor = "#0000FF"
                    cornerRadius = CornerRadius(radius = 16.0)
                    margin = EdgeValue(
                        left = UnitValue(25.0),
                        right = UnitValue(25.0),
                        top = UnitValue(15.0)
                    )
                }
            )
        )
    )
}

Após criadas as telas, segue um exemplo de criação de serviço:

import br.com.zup.beagle.widget.layout.ScreenBuilder
import br.com.zup.grpc.BeagleScreenService
import net.devh.boot.grpc.server.service.GrpcService
import br.com.zup.grpcbff.screen.HomeScreen
import br.com.zup.grpcbff.screen.SplashScreen

@GrpcService
class MyBeagleAppService: BeagleScreenService() {
    override fun screens(): Map<String, (String) -> ScreenBuilder> {
        return mapOf(
            "home" to { params -> HomeScreen(params) },
            "splash" to { SplashScreen },
        )
    }
}
  • No lado do cliente: sua aplicação deve implementar um HTTP Client fornecido pela lib do Beagle gRPC. Ele será responsável por receber, tratar e traduzir (desserilizar) qualquer requisição gRPC.
const val BASE_URL = "http://10.0.2.2:8080" // your gRPC host

@BeagleComponent
class AppHttpClientFactory: HttpClientFactory {
    override fun create(): HttpClient {
        return GrpcClient(BASE_URL, HttpClientDefault())
    }
}

Beagle com gRPC: não para por aqui!

Essa imagem representa uma expressão de concentração, onde uma pessoa está pensativa e fazendo alguns calculos mentais para tentar entender uma situação.

Achou confuso? Não se preocupe! Temos mais detalhes sobre como usar o Beagle com gRPC tanto no front-end, quanto no back-end. Basta conferir a nossa documentação oficial.

O que achou dessa ideia de implementação de gRPC? Se quiser conhecer outras funcionalidades do nosso projeto open source, fica aqui o convite para você dar uma olhada no nosso fórum ou conferir o projeto pelo GitHub.

Referências:

capa do artigo o que é gRPC e como usá-lo no Beagle que mostra um programador homem desenvolvendo com três telas.
Foto Gabriel Maximo
Desenvolvedor Back-end
Sou desenvolvedor back-end desde agosto de 2019, curso Ciência da Computação pela Universidade Federal de Uberlândia e tenho objetivo de me tornar especialista back-end. Trabalhar com projetos Open Source no Brasil me trouxe aprendizados, novas habilidades e oportunidades. Criar conteúdo é uma forma de retribuir a uma comunidade a qual eu devo mais do que conseguiria pagar!

Este site utiliza cookies para proporcionar uma experiência de navegação melhor. Consulte nossa Política de Privacidade.