Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Introducción

gRPC es un framework de procedimiento remoto de alto rendimiento desarrollado por Google. Utiliza el protocolo HTTP/2 para la comunicación entre los servidores y los clientes, y permite la comunicación entre los servicios de diferentes lenguajes de programación.

Configuración del entorno

Info

En el archivo build.gradle se añadieron las dependencias necesarias de gRPC

Code Block
    testImplementation 'io.grpc:grpc-testing:1.41.0'
    testImplementation group: 'com.google.protobuf', name: 'protobuf-java', version:'3.23.2'
    implementation 'io.grpc:grpc-stub:1.53.0'
    implementation 'io.grpc:grpc-api:1.53.0'
    implementation 'io.grpc:protoc-gen-grpc-java:1.53.0'
    implementation 'io.grpc:grpc-core:1.53.0'
    implementation 'io.grpc:grpc-netty-shaded:1.53.0'
    implementation 'com.google.api.grpc:proto-google-common-protos:2.14.1'
    implementation 'javax.annotation:javax.annotation-api:1.3.2'
    implementation 'io.grpc:grpc-protobuf:1.55.1'

Archivos .proto

En gRPC, los servicios y los mensajes que se envían entre el cliente y el servidor se definen en archivos .proto, que utilizan el lenguaje de definición de interfaz (IDL) de Protocol Buffers. Aquí es donde se definen las operaciones que el servicio puede realizar y los tipos de datos que se envían y reciben. Esencialmente, es la especificación de la API de gRPC.

Info

Agregar los archivos .proto necesarios para las pruebas en src/main/proto

Stubs

Un "stub" en gRPC es un término utilizado para referirse al cliente de un servicio gRPC que se conecta a un servidor. Es esencialmente una pieza de código generada a partir del archivo .proto que un cliente puede usar para invocar métodos de un servicio remoto. Toma un mensaje de protocolo, serializa el mensaje en el formato correcto, envía la solicitud a través de la red, y luego espera y deserializa las respuestas para enviarlas de vuelta al código de llamada.

El enfoque más común para realizar pruebas en Java con gRPC es utilizar un stub generado automáticamente. Esto permite enfocarse en probar la lógica específica del cliente sin preocuparse por la complejidad de la comunicación subyacente.

Generar los archivos Java a partir del archivo .proto:

Gradle posee un plugin que permite generar los archivos Java, los cuales incluyen el código para los servicios y mensajes a partir de los archivos .proto, utilizando el compilador de Protocol Buffers (protobuf).

Info

Se cuenta con el plugin de protobuf al archivo build.gradle:

Code Block
apply 
plugin
'com.google.protobuf'
Info

También, se incluye la siguiente configuración para el plugin:

Code Block
protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:3.23.2'
    }
    plugins{
        grpc{
            artifact = 'io.grpc:protoc-gen-grpc-java:1.53.0'
        }
    }
    generateProtoTasks {
        all()*.plugins {
            grpc{
            }
        }
    }

}

Para que el plugin compile los archivos .proto se ejecuta el comando gradle build y se generen los archivos Java necesarios.

Los stubs serán generados en el directorio build/generated/source/proto/main/grpc.

Note

Si se desea no utilizar un stub y probar la comunicación con un servidor gRPC , se tendría que implementar manualmente toda la lógica de comunicación, serialización, deserialización y manejo de la comunicación de red, lo que puede ser bastante complejo y propenso a errores.

Tipos de Stubs en gRPC

Blocking (síncrono)

Realiza llamadas síncronas. Esto significa que cuando se hace una llamada a un método en el stub, la ejecución de ese hilo se bloquea hasta que se recibe la respuesta del servidor. Este comportamiento es útil en situaciones en las que se necesita esperar la respuesta del servidor antes de continuar con la ejecución del programa, como cuando se está realizando una operación de consulta o actualización de datos.

Non-blocking (Future stub)

Las llamadas son no bloqueantes, lo que significa que la llamada devuelve inmediatamente un Future que el cliente puede usar para obtener la respuesta cuando esté disponible.

Async (asíncrono)

Las llamadas son asincrónicas. El cliente debe pasar un StreamObserver a la llamada que será llamado cuando la respuesta esté disponible.

Implementación del cliente

Después de generar el código del cliente y del servidor, se implementan los stubs en los script de prueba.

Creación del tipo de Stub

En gRPC en necesario especificar el tipo de stub (cliente) que que se requiere usar para hacer una petición. El tipo de stub que se elija, determina cómo se maneja la petición.

Para seleccionar el tipo de stub, se deben usar los métodos correspondientes de la clase generada automáticamente a partir del .proto.

Por ejemplo, si el servicio se llama AccountAggregationService, gRPC generará una clase AccountAggregationServiceGrpc que contiene métodos: newBlockingStub, newFutureStub, y newStub que se pueden usar para crear los distintos tipos de stubs.

A continuación se especifica como se crea un stub de gRPC bloqueante para la interfaz AccountAggregationService. Esto es esencialmente un cliente que se usará para hacer llamadas al servicio.

Code Block
AccountAggregationServiceGrpc.AccountAggregationServiceBlockingStub = AccountAggregationServiceGrpc.newBlockingStub();

ServiceBase.java

Se optó por crear una clase padre que mantuviera la estructura abstracta para la apertura, cierre de los canales y la creación del tipo de stub que todas las pruebas de servicios GRPC deben tener. De esta manera, las clases hijas son responsables de definir los detalles específicos.

ServiceBase.java es una clase abstracta genérica que proporciona una estructura básica para la creación de servicios y utiliza la librería de gRPC para la creación de canales y stubs.

Esta clase administra un ManagedChannel y un AbstractStub (referenciado genéricamente como T). El ManagedChannel es el medio principal de comunicación entre el cliente y el servidor en gRPC, y el AbstractStub es una representación genérica de un servicio gRPC en el lado del cliente.

ServiceBase se ocupa de la creación y cierre del ManagedChannel, pero delega la creación del AbstractStub a las subclases a través del método abstracto buildStub. El método buildStub se llama después de que se ha creado el ManagedChannel, en el método setup, para que las subclases puedan utilizar el canal para construir su stub.

ServiceNameExample

AccountAggregationServiceBase.java

AccountAggregationServiceBase es una subclase concreta de ServiceBase que proporciona una implementación específica del método buildStub. Esta clase representa un servicio de agregación de cuentas y utiliza el stub de bloqueo específico para este servicio, AccountAggregationServiceGrpc.AccountAggregationServiceBlockingStub.

Por lo tanto, AccountAggregationServiceBase se beneficia de la gestión del ManagedChannel proporcionada por ServiceBase, y solo necesita preocuparse por la creación del stub correcto para su servicio específico.

La ventaja de este enfoque es que permite reutilizar el código común de la gestión del ManagedChannel entre varios servicios, manteniendo al mismo tiempo la flexibilidad para utilizar diferentes stubs según las necesidades de cada servicio. Esto resulta en un código más limpio, modular y fácil de mantener.

Definición de los objetos

Las definiciones de objetos para la creación de stubs se han separado en una clase distinta ConstsGRPC.java del proyecto de automatización para simplificar el código y mejorar su comprehensión.

Para el ejemplo anterior se define de la siguiente manera:

Code Blockpublic static AccountAggregationServiceGrpc

.

AccountAggregationServiceBlockingStub AccountAggregationServiceBlockingStub;

Y se tiene una clase llamada TokenDigital.java que extiende de ConstsGRPC.java para manejar los métodos que crean los blocking stubs

Code Block@Step("Se obtiene el Blocking Aggregation Service") public static void accountAggregationServiceBlocking() { AccountAggregationServiceBlockingStub = AccountAggregationServiceGrpc.newBlockingStub(channel); }