The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

Introdução ao gRPC

Esta página explica como começar a usar o gRPC na sua aplicação Quarkus. Embora esta página descreva como configurá-lo com o Maven, também é possível usar o Gradle.

Vamos imaginar que o você tenha um projeto Quarkus normal, gerado a partir do gerador de projetos Quarkus . A configuração padrão é suficiente, mas você também pode selecionar algumas extensões, se desejar.

Solução

Recomendamos que você siga as instruções nas próximas seções e crie a aplicação passo a passo. No entanto, você pode ir direto para o exemplo completo.

Clone o repositório Git: git clone https://github.com/quarkusio/quarkus-quickstarts.git, ou baixe um arquivo.

A solução está localizada no diretório grpc-plain-text-quickstart.

Configurando seu projeto

Adicione a extensão Quarkus gRPC ao seu arquivo de build:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-grpc</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-grpc")

By default, the quarkus-grpc extension relies on the reactive programming model. In this guide we will follow a reactive approach. Under the dependencies section of your pom.xml file, make sure you have the Quarkus REST (formerly RESTEasy Reactive) dependency:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-rest</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-rest")

Se você estiver usando o Maven, certifique-se de que a meta generate-code do quarkus-maven-plugin esteja habilitado no seu pom.xml . Se quiser gerar código a partir de diferentes arquivos proto para testes, adicione também a meta generate-code-tests . Observe que nenhuma tarefa/meta adicional é necessária para o plug-in do Gradle.

<build>
    <plugins>
        <plugin>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-maven-plugin</artifactId>
            <version>${quarkus-plugin.version}</version>
            <extensions>true</extensions>
            <executions>
                <execution>
                    <goals>
                        <goal>build</goal>
                        <goal>generate-code</goal>
                        <goal>generate-code-tests</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Com essa configuração, você pode colocar as definições do seu serviço e mensagens no diretório src/main/proto. O quarkus-maven-plugin irá gerar arquivos Java a partir dos seus arquivos proto.

O quarkus-maven-plugin recupera uma versão do protoc (o compilador protobuf) dos repositórios Maven. A versão recuperada corresponde ao seu sistema operacional e arquitetura de CPU. Se essa versão recuperada não funcionar no seu contexto, você pode forçar o uso de um classificador de sistema operacional diferente com -Dquarkus.grpc.protoc-os-classifier=seu-classificador-de-os (por exemplo, osx-x86_64). Você também pode baixar o binário adequado e especificar a localização via -Dquarkus.grpc.protoc-path=/caminho/para/protoc.

Vamos começar com um simples Hello service. Crie o arquivo src/main/proto/helloworld.proto com o seguinte conteúdo:

syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.quarkus.example";
option java_outer_classname = "HelloWorldProto";

package helloworld;

// The greeting service definition.
service Greeter {
    // Sends a greeting
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
    string name = 1;
}

// The response message containing the greetings
message HelloReply {
    string message = 1;
}

Este arquivo proto define uma interface de serviço simples com um único método ( SayHello), e as mensagens trocadas ( HelloRequest contendo o nome HelloReply e contendo a mensagem de saudação).

O seu arquivo proto não pode conter option java_generic_services = true;. Os serviços genéricos estão obsoletos e não são compatíveis com os plugins de geração de código do Quarkus.

Antes de começar a programar, precisamos gerar as classes usadas para implementar e consumir os serviços gRPC. Em um terminal, execute:

$ mvn compile

Uma vez gerado, pode consultar o diretório target/generated-sources/grpc:

target/generated-sources/grpc
└── io
    └── quarkus
        └── example
            ├── Greeter.java
            ├── GreeterBean.java
            ├── GreeterClient.java
            ├── GreeterGrpc.java
            ├── HelloReply.java
            ├── HelloReplyOrBuilder.java
            ├── HelloRequest.java
            ├── HelloRequestOrBuilder.java
            ├── HelloWorldProto.java
            └── MutinyGreeterGrpc.java

Estas são as classes que vamos utilizar.

Diferentes implementações / tipos de gRPC

Outra coisa importante a se notar é que o suporte do Quarkus para gRPC atualmente inclui 3 diferentes tipos de uso do gRPC:

  1. implementação antiga do Vert.x gRPC com um servidor gRPC separado (padrão)

  2. nova implementação Vert.x gRPC em cima do servidor HTTP existente

  3. xDS gRPC wrapper sobre grpc-java com um servidor gRPC separado baseado no Netty

Documentações adicionais explicam como habilitar e usar cada um deles.

Implementação de um serviço gRPC

Agora que temos as classes geradas, vamos implementar o nosso serviço hello.

Com o Quarkus, implementar um serviço requer a implementação da interface de serviço gerada com base no Mutiny, uma API de Programação Reativa integrada no Quarkus, e expô-la como um bean CDI. Saiba mais sobre o Mutiny no [guia Mutiny](xref:mutiny-primer.adoc). A classe de serviço deve ser anotada com a anotação @io.quarkus.grpc.GrpcService.

Implementação de um serviço

Crie o arquivo src/main/java/org/acme/HelloService.java com o seguinte conteúdo:

package org.acme;

import io.quarkus.example.Greeter;
import io.quarkus.example.HelloReply;
import io.quarkus.example.HelloRequest;
import io.quarkus.grpc.GrpcService;
import io.smallrye.mutiny.Uni;

@GrpcService (1)
public class HelloService implements Greeter {  (2)

    @Override
    public Uni<HelloReply> sayHello(HelloRequest request) { (3)
        return Uni.createFrom().item(() ->
                HelloReply.newBuilder().setMessage("Hello " + request.getName()).build()
        );
    }
}
1 Exponha a sua implementação como um bean.
2 Implementar a interface de serviço gerada.
3 Implementar os métodos definidos na definição do serviço (neste caso, temos um único método).

Você também pode usar a API gRPC padrão em vez do Mutiny:

package org.acme;

import io.grpc.stub.StreamObserver;
import io.quarkus.example.GreeterGrpc;
import io.quarkus.example.HelloReply;
import io.quarkus.example.HelloRequest;
import io.quarkus.grpc.GrpcService;

@GrpcService (1)
public class HelloService extends GreeterGrpc.GreeterImplBase { (2)

    @Override
    public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) { (3)
        String name = request.getName();
        String message = "Hello " + name;
        responseObserver.onNext(HelloReply.newBuilder().setMessage(message).build()); (4)
        responseObserver.onCompleted(); (5)
    }
}
1 Exponha a sua implementação como um bean.
2 Estende a classe ImplBase. Esta é uma classe gerada.
3 Implementar os métodos definidos na definição do serviço (neste caso, temos um único método).
4 Construir e enviar a resposta.
5 Fechar a resposta.
Se a lógica de implementação do seu serviço for bloqueante (usando E/S bloqueante, por exemplo), anote seu método com @Blocking. A anotação io.smallrye.common.annotation.Blocking instrui o framework a invocar o método anotado em uma thread de trabalho em vez da thread de E/S (event-loop).

O servidor gRPC

Os serviços são served by a server . Os serviços disponíveis (beans CDI ) são automaticamente registrados e expostos.

Por padrão, o servidor é exposto em localhost:9000 e utiliza texto simples (sem TLS) quando executado normalmente, e localhost:9001 para testes.

Executar a aplicação utilizando: mvn quarkus:dev.

Consumindo um serviço gRPC

Nesta seção, vamos consumir o serviço que expomos. Para simplificar, vamos consumir o serviço a partir da mesma aplicação, o que no mundo real não faz sentido.

Abra a classe org.acme.ExampleResource e edite o conteúdo para ficar:

package org.acme;

import io.quarkus.example.Greeter;
import io.quarkus.example.HelloRequest;
import io.quarkus.grpc.GrpcClient;
import io.smallrye.mutiny.Uni;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/hello")
public class ExampleResource {

    @GrpcClient                               (1)
    Greeter hello;                            (2)

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello";
    }

    @GET
    @Path("/{name}")
    public Uni<String> hello(String name) {
        return hello.sayHello(HelloRequest.newBuilder().setName(name).build())
                .onItem().transform(helloReply -> helloReply.getMessage());  (3)
    }
}
1 Injete o serviço e configure seu nome. O nome é utilizado na configuração da aplicação. Se não for especificado, é utilizado o nome do campo: hello neste caso específico.
2 Use a interface de serviço gerada com base na API Mutiny.
3 Invocar o serviço.

Precisamos configurar a aplicação para indicar onde o serviço hello é encontrado. No arquivo src/main/resources/application.properties , adicione a seguinte propriedade:

quarkus.grpc.clients.hello.host=localhost
  • hello é o nome utilizado na anotação @GrpcClient.

  • host configura o host do serviço (aqui é localhost).

Em seguida, abra http://localhost:8080/hello/quarkus em um navegador e deverá receber Hello quarkus!

Empacotando a aplicação

Como qualquer outra aplicação Quarkus, você pode empacotá-la com: mvn package. Você também pode empacotar a aplicação em um executável nativo com: mvn package -Dnative.

Conteúdo Relacionado