Suporte a Threads Virtuais do Quarkus para serviços gRPC
Este guia explica como se beneficiar dos threads virtuais Java ao implementar um serviço gRPC.
|
Este guia se concentra no uso de threads virtuais com as extensões gRPC. Consulte Escrevendo serviços REST reativos mais simples com o suporte a Threads Virtuais do Quarkus para saber mais sobre os threads virtuais Java em geral e o suporte a Threads Virtuais do Quarkus. |
Por padrão, a extensão gRPC do Quarkus invoca métodos de serviço em um thread de loop de evento. Consulte a documentação da Arquitetura Reativa do Quarkus para obter mais detalhes sobre esse tópico. Mas você também pode usar a anotação @Blocking para indicar que o serviço está bloqueando e deve ser executado em um thread de trabalho.
A ideia por trás do suporte a Threads Virtuais do Quarkus para serviços gRPC é descarregar a invocação do método de serviço em threads virtuais, em vez de executá-lo em um thread de loop de evento ou em um thread de trabalho.
Para ativar o suporte a thread virtual em um método de serviço, basta adicionar a anotação @RunOnVirtualThread ao método. Se o JDK for compatível (Java 19 ou versões posteriores - recomendamos 21+), a invocação será transferida para um novo thread virtual. Assim, será possível executar operações de bloqueio sem bloquear o thread da plataforma no qual o thread virtual está montado.
Configurando serviços gRPC para usar threads virtuais
Vamos ver um exemplo de como implementar um serviço gRPC usando threads virtuais. Primeiro, certifique-se de ter a dependência da extensão gRPC em seu arquivo de construção:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-grpc</artifactId>
</dependency>
implementation("io.quarkus:quarkus-grpc")
Você também precisa se certificar de que está usando o Java 19 ou posterior (recomendamos o 21+), o que pode ser garantido no arquivo pom.xml com o seguinte:
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
Execute sua aplicação com:
java -jar target/quarkus-app/quarkus-run.jar
ou para utilizar o modo Quarkus Dev, insira o seguinte na configuração quarkus-maven-plugin:
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
</goals>
</execution>
</executions>
<configuration>
<source>21</source>
<target>21</target>
</configuration>
</plugin>
Em seguida, pode começar a utilizar a anotação @RunOnVirtualThread na implementação do seu serviço:
package io.quarkus.grpc.example.streaming;
import com.google.protobuf.ByteString;
import com.google.protobuf.EmptyProtos;
import io.grpc.testing.integration.Messages;
import io.grpc.testing.integration.TestService;
import io.quarkus.grpc.GrpcService;
import io.smallrye.common.annotation.RunOnVirtualThread;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;
@GrpcService
public class TestServiceImpl implements TestService {
@RunOnVirtualThread
@Override
public Uni<EmptyProtos.Empty> emptyCall(EmptyProtos.Empty request) {
return Uni.createFrom().item(EmptyProtos.Empty.newBuilder().build());
}
@RunOnVirtualThread
@Override
public Uni<Messages.SimpleResponse> unaryCall(Messages.SimpleRequest request) {
var value = request.getPayload().getBody().toStringUtf8();
var resp = Messages.SimpleResponse.newBuilder()
.setPayload(Messages.Payload.newBuilder().setBody(ByteString.copyFromUtf8(value.toUpperCase())).build())
.build();
return Uni.createFrom().item(resp);
}
@Override
@RunOnVirtualThread
public Multi<Messages.StreamingOutputCallResponse> streamingOutputCall(Messages.StreamingOutputCallRequest request) {
var value = request.getPayload().getBody().toStringUtf8();
return Multi.createFrom().<String> emitter(emitter -> {
emitter.emit(value.toUpperCase());
emitter.emit(value.toUpperCase());
emitter.emit(value.toUpperCase());
emitter.complete();
}).map(v -> Messages.StreamingOutputCallResponse.newBuilder()
.setPayload(Messages.Payload.newBuilder().setBody(ByteString.copyFromUtf8(v)).build())
.build());
}
}
|
Limitações
Os métodos gRPC que recebem fluxos, como um |