Introducción
La comunicación entre microservicios prácticamente es la conexión con sistemas internos o externos tanto de forma síncrona o asíncrona, detallamos estos patrones de forma sencilla, resumida y con ejemplos.
Los patrones en los que en la mayoría se trabajará son patrones probados, definidos y usados en practica hoy en día, nos basaremos en el libro de Design Pattern for Cloud Native Application.
Patrones de mensajería síncrona
Patrón Request-Response
Concepto
Es un de los patrones utilizados comúnmente se tiene una fuente externa (un componente, sistema o un cliente) que realiza una solicitud hacía el microservicio, por ende genera un bloqueo hasta recibir la respuesta, manteniendo un canal de comunicación hasta que la fuente externa reciba la respuesta deseada.
Normalmente en este patrón el microservicio que envía la respuesta esta acoplado con otros microservicios, a medida que aumenta la cantidad de microservicios genera un cuello de botella y la generación de mayores canales de comunicación, aumentando considerablemente el tiempo de espera.
Existe un patrón relacionado de orquestación y delimitación de salida de servicios, llamado API Gateway.
Implementación
Para esta implementación seremos la fuente externa que deberá conectarse a un servicio que responda sobre una aproximación de donde estamos ubicados en base a la IP.
Este primer bloque define la implementación de consumo de un servicio externo.
@Path("")
@RegisterRestClient(configKey = "ipinfo")
public interface InformationService {
@GET
IpInformation getIP();
}
Ejecutando el código con la ruta localhost:8080/ip obtendremos la info de nuestra conexión IP.
Consideraciones para el uso de este patrón
Genera un mayor acoplamiento entre microservicios
Los servicios esperarán la respuesta del servicio invocado
Se puede utilizar para cantidades pequeñas de microservicios (menor a 10)
Utilizar cuando no tiene dependencias para traer la información a tiempo real
Patrón RPC
En realidad RPC (Remote Procedure Call), recordé de CORBA en su momento, no es un patrón correspondiente pero este tipo de comunicación gano popularidad hace un tiempo atrás y volvió a ganar la popularidad nuevamente cuando google hizo una implementación llamándola gRPC.
Entonces gRPC se usa por medio de HTTP2 y puede comunicarse sin ningún problema o limitación técnica.
Diferencias entre RPC y gRPC
Existen diferencias entre RPC y gRPC, la siguiente tabla muestra lo que considero más relevante para diferenciarlos.
RPC | gRPC |
se puede comunicar por: UDP/TCP/HTTP | HTTP/2 |
El formato para serializarlo puede ser cualquiera, normalmente XML o JSON | El formato de conversión es un proto |
Implementación
Implementamos un sayHello correspondiente, es decir el gRPC implementado como publicador
@GrpcService
public class HelloGrpcService implements HelloGrpc {
@Override
public Uni<HelloReply> sayHello(HelloRequest request) {
return Uni.createFrom().item("Hello " + request.getName() + "!")
.map(msg -> HelloReply.newBuilder().setMessage(msg).build());
}
}
Un archivo importante para ello es el .proto con las instrucciones de donde debe de crearse la carpeta, que método y clases creará, en nuestro caso utilizamos el siguiente:
syntax = "proto3";
option java_multiple_files = true;
option java_package = "clp.coder";
option java_outer_classname = "HelloGrpcProto";
package hello;
service HelloGrpc {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
Ejecutamos el código con el comando mvn quarkus:dev
y veremos que mediante un puerto se establecerá la comunicación gRPC.
Utilizando un postman podemos hacer la consulta correspondiente enviando un nombre:
Igualmente en nuestras pruebas unitarias obtenemos resultados correspondientes haciendo invocación gRPC, el punto 1 muestra el despliegue correcto del servicio gRPC desplegado en el puerto asignado(9990), y el puerto de default 8081 para las pruebas en Quarkus
Consideraciones para el uso de este patrón
Comunicación entre microservicios, siempre y cuando alguna restricción tecnológica le impida hacer una implementación SOAP, RESTful, JSON u otro.
No es una buena opción si esta pensando en exponer a consumidores externos
Puede ser utilizado como un Service as Abstraction si es que tiene implementaciones nativas RPC
Recursos
Repositorio: https://github.com/ChristianLoza/cloud-pattern.design
Las imagenes expuestas son autoría mía con excepción de la portada del libro de patrones de diseño nativas en la nube.
Conclusiones
Ningún patrón es mejor que otro, debe considerar el volumen de microservicios si es que quiere utilizar patrones síncronos.
Se debe de considerar las limitaciones que ofrece una comunicación directa entre microservicios en base a cantidad.