Se denomina a RPC como las llamadas a procedimiento remoto (Remote Procedure Call) gRPC es un framework de RPC Universal de código abierto y de alto rendimiento.
Por llamadas a procedimiento remoto entendemos que una aplicación en una máquina ejecuta un método de otra aplicación de otra máquina, de tal forma que no nos vamos a preocupar de la comunicación entre ambas máquinas. Es como si estuviéramos invocando una método de nuestra aplicación
gRPC, como framework de RPC, va a hacer por nosotros gran parte de la lógica común necesaria al implementar un servicio RPC. Al ser universal, significa que un servicio RPC levantado en cualquier lenguaje, va a poder ser invocado por cualquier otra aplicación realizada en cualquier otro lenguage.
Inicialmente los servicios gRPC, van a ser especialmente interesantes en un entorno de de microservicios, ya que actualmente tiene soporte limitado en navegadores, aunque existen proyectos abiertos para esto que por el momento no garantizan continuidad (gRPC-Web)
gRPC utiliza protobuf para realizar los intercambios de datos. Esto es un mecanismo para intercambiar información de forma eficiente, ya que consigue más velocidad y además consigue mensajes más ligeros evitando el desperdicio de ancho de banda
Admite traspaso de información entre el cliente y servidor de forma bi-direccional.
gRPC está pensado especialmente, como se ha mencionado anteriormente, en el uso de microservicios ligeros, donde la eficiencia es critica, ya que consiguen una alta velocidad de ejecución/transmisión de datos.
Ficheros .proto
gRPC usa una aproximación de contrato primero (contract-first) para el desarrollo de API. Los búferes de protocolo (Protobuf) se usan de forma predeterminada como el lenguaje de definición de interfaz (IDL). El archivo *.proto contiene lo siguiente:
La definición del servicio gRPC
La definición de los tipos (types) utilizados entre clientes y servidores
Existe multitud de opciones para definir el servicio mediante el protocolo protobuf, no obstante a continuación se enumeran los aspectos fundamentales que son necesarios para la deficinición del mismo.
Definición del servicio:
[scss]// The service definition.
service HelloCommunityService {
// Endpoints definition
rpc SayHello(RequestMessage) returns (RequestReply);
rpc SayBye(RequestMessage) returns (RequestReply);
}[/scss]
Mediante la palabra service, se define el servicio, indicando los métodos que estarán disponibles (similar a los endpoints de un servicio api).
Mediante la palabra rpc, se definen cada uno de los métodos que estarán disponibles para ser consumidos desde el cliente.
En este caso vamos a tener dos métodos que podrán ser utilizados:
- SayHello
- SayBye
De esta forma, definimos el nombre del método, SayHello, indicando que va a recibir un dato de tipo
RequestMessage y devolverá un dato de tipo RequestReply
Definición de los tipos
[scss]// The request message used for «in data»
message RequestMessage {
string name = 1;
}
// The response message used for «out data»
message RequestReply {
string message = 1;
}[/scss]
Mediante la palabra message definiremos los tipos de mensajes que vamos a utilizar en los métodos del servicio, para recibir y enviar datos.
En este caso disponemos de dos tipos diferentes:
- RequestMessage
- RequestReply
De esta forma definimos el nombre del tipo RequestMessage, con la enumeración de las propiedades que contendrá.
Como podréis observar cada propiedad tiene un número único. Estos número son utilizados para definir los campos una vez el mensaje se convierte a formato binario y no deberían ser cambiados, una vez el mensaje sea usado.
Generación de clases base
Una vez creado el fichero .proto, y cada vez que sea moficado, al ser grabado o bien al ser compilado, se va a generar la clase base que podremos utilizar para la explotación del servicio.
Esto nos va a crear una clase base abstracta, con todas las definiciones que se incluyen en el fichero .proto, que nos va a servir para poder definir el contenido de cada uno de los métodos definidos en el servicio.
Aplicación Servidor
Podemos generar aplicaciones que soporte gRPC, mediante Visual Studio de forma sencilla utilizando la plantilla para gRPC, o bien desde Visual Code a través de la consola de comandos.
Podemos perfectamente también crear el proyecto a través de la consola, y editar los ficheros con Visual Studio Code. Para ello seguiremos los siguientes pasos:
- Abrimos una nueva ventana de Terminal en Code.
- Una vez situados en la carpeta donde queremos generar el proyecto, ejecutamos los siguientes
[javascript]dotnet new grpc -o GrpcServiceServer
code -r GrpcServiceServer[/javascript]
Una vez creado el proyecto podremos ejecutarlo con el siguiente comando:
Para confiar en el certificado de desarrollo de HTTPS, ejecute el comando siguiente:
[javascript]dotnet dev-certs https –trust[/javascript]
Una vez creado el proyecto podremos ejecutarlo con el siguiente comando:
[javascript]dotnet run[/javascript]
Aplicación Cliente
De igual forma que hemos indicado que es posible crear el servidor gRPC, desde Visual Studio y desde Visual Studio Code, para crear la aplicación cliente, también tenemos las dos opciones.
Obviamente cambiamos a una nueva carpeta, donde se creará la aplicación y a continuación:
En este caso ejecutaríamos en la ventana de terminal el siguiente comando:
[javascript]dotnet new console -o GrpcServiceClient code
-r GrpcServiceClient[/javascript]
Añadir paquetes nuget
El proyecto de cliente gRPC requiere los siguientes paquetes NuGet:
- Grpc.Net.Client, que contiene el cliente de .NET Core.
- Google.Protobuf, que contiene API de mensajes protobuf para C#.
- Grpc.Tools, que contiene compatibilidad con herramientas de C# para archivos protobuf. El paquete de herramientas no es necesario en el runtime, de modo que la dependencia se marca con PrivateAssets=»All».
Para añadir los paquetes procederemos de la siguiente forma:
Ejecutamos los siguientes comandos en el terminal integrado:
[javascript]dotnet add GrpcServiceClient.csproj package Grpc.Net.Client
dotnet add GrpcServiceClient.csproj package Google.Protobuf
dotnet add GrpcServiceClient.csproj package Grpc.Tools[/javascript]
Añadir referencia del api de servicio
Los ficheros .proto serán los ficheros que realmente nos van a dar una Api de explotación del servicio, donde estarán definidos los servicios existentes (endpoints) y los tipos de mensajes que se utilizan en la transación de datos.
Para incluir el archivo .proto en un proyecto, hay que agregarlo al grupo de elementos , en el fichero de proyecto:
[scss]<ItemGroup>
<Protobuf Include=»Protos\HelloCommunity.proto» GrpcServices=»Server» />
</ItemGroup>[/scss]
El fichero .proto, se puede añadir al proyecto de las siguientes formas:
Copiaremos el fichero proto en la carpeta que hemos creado
Creamos una carpeta Protos
Copiamos el fichero .proto en la carpeta
Crear el cliente de acceso al servicio
Una vez añadido el fichero .proto, debemos compilar el proyecto para que se generen los espacios de nombre y tipos definidos para el servicio gRPC.
Mediante las siguientes líneas:
[scss]using var channel = GrpcChannel.ForAddress(«https://localhost:7172»); var
client = new HelloCommunityService.HelloCommunityServiceClient(channel);[/scss]
- Creamos una instancia de GrpcChannel, donde se encuentra la información necesaria para crear la conexión al servicio gRPC.
- Una vez creada una instancia de GrpcChannel, la utilizamos para crear el cliente del servicio defnido en el fichero .proto, en este caso HelloCommunity
A partir de aquí utilizaremos el cliente creado (client) para explotar los métodos disponibles del servicio, en nuestro caso
- SayHello
- SayBye
[scss]var reply = await client.SayHelloAsync(new RequestMessage { Name = «Community member» });
Console.WriteLine(«Greeting from Server: » + reply.Message);
reply = await client.SayByeAsync(new RequestMessage { Name = «Community member» });
Console.WriteLine(«Greeting from : » + reply.Message);[/scss]
Una vez que tenemos todo podemos probar el servicio. Ejecutamos el cliente y el servidor.
Para ello ejecutaremos en la ventana de comandos de cada carpeta de proyecto lo siguiente:
[javascript]dotnet run[/javascript]
En cualquier caso ejecutaremos primero el servicio de gRPC (server).
A continuación, se puede ver el resultado del cliente, así como las trazas de información del servidor respondiendo a las solicitudes del servicio.