arrow_back Volver
Inicio keyboard_arrow_right Artículos keyboard_arrow_right Artículo

¿Cómo crear aplicaciones en tiempo real?

Eduardo Ismael Garcia

Full Stack Developer at Código Facilito.

av_timer 5 Min. de lectura

remove_red_eye 10831 visitas

calendar_today 24 Junio 2020

Un sistema de notificaciones en tiempo real es sin duda pieza clave para el exito de nuestras aplicaciones, claro, siempre y cuando deseemos nuestros usuarios se encuentren sabedores de los últimos eventos en la plataforma.

Las notificaciones no solo alertar a los usuarios que algo ha sucedido, sino que son parte fundamental en procesos de suma importancia. Por ejemplo, si tenemos un sistema de ventas online, lo ideal sería notificar a los vendedores siempre que haya ocurrido una nueva compra, su stock este por agotarse o inclusive cuando un usuario pregunte por alguno de sus productos, de igual forma a los compradores hay que notificarlos del estatus de su compra, el envío de su producto, así como de ciertas disputas que puedan ocurrir, todo esto, por supuesto en tiempo real.

Otro ejemplo puede ser en el ambito de los vídeojuegos, especialmente en el multiplayer, donde deseamos que ciertos eventos se vean reflejados, en tiempo real para todos los jugadores.

Hablar de implementar un sistema de notificaciones en tiempo real puede sonar algo retador, un feature que puede tomarnos un par días o inclusives semanas; y de hecho esto tiene algo de cierto, sin embargo déjame decirte que esto, es proceso un poco menos complejo de lo que uno puede llegar a pensar, claro, siempre y cuando utilicemos el paradigma y el enfoque correcto.

Es por ello que, en esta ocasión, me gustaría habláramos sobre el paradigma/arquitectura PubSub, el cual sin duda no será de mucha utilidad siempre que deseemos crear aplicaciones en tiempo real. El tema es muy interesante, y no dudo que podrás sacarle el máximo provecho posible. 🎉

Bien una vez dicho todo esto, comencemos.

PubSub

Por si nunca habías escuchado acerca de PubSub, no te preocupes, aquí te lo explico. Verás, PubSub, también conocido como Publish/Subscribe, es un arquitectura la cual nos permite enviar un mensaje a múltiples usuarios en tiempo real.

Dentro de esta arquitectura existen dos entidades de suma importancias, el editor (Publisher) y el subscriptor (Subscriber).

Su funcionamiento podemos definirlo en cuatro sencillos pasos.

  • Un editor crea un nuevo canal.
  • Todos aquellos subscriptores interesados en un canal, pueden subscribirse a él.
  • El editor envía un mensaje a través canal, sin previo conocimiento de quienes están subscritos en él. *Todos los subscriptores en el canal reciben el mensaje sin conocer al editor.

Lo interesante de todo esto es la facilidad con la cual un mensaje puede ser replicado a una n cantidad de usuarios en tiempo real. Si bien es cierto el "anonimato" en este paradigma existe, y es prácticamente imposible para el escritor conocer todos los subscriptores en el canal, así como a los subscriptores se les es imposible conocer al escritor, esto pequeño detalle, el desacoplamiento de ambas partes, permite mayor escalabilidad en la red, pudiendo así tener canales con miles de subscriptores.

Ahora, quizás te estés preguntando ¿Cómo puedo implementar PubSub en mi proyecto? La respuesta es sencilla, podemos utilizar Redis.

PubSub con Redis

Afortunadamente redis nos permite implementar PubSub de una forma muy sencilla. Veamos un par de ejemplos.

Lo primero que debemos hacer será iniciar el servicio de Redis. En mi caso he descargado y compilado el proyecto, tú sin embargo puedes hacer uso de redis-cli.

Nos situamos en nuestras terminal y ejecutamos el siguiente comando. Si al igual que yo compilaste redis, muy probablemente tengas que moverte de directorio.

./redis-server

Si todo ha salido bien, debemos obtener como resultado la siguiente salida. 🚀

                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 3.0.7 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 9765
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'            

Ahora seremos capaces de conectarnos con el servidor mediante un cliente.

En una nueva venta, ejecutamos los siguientes comandos.

Primero nos autenticamos con el servidor.

./redis-cli 

A través del comando SUBSCRIBE, seremos capaces de subscribirnos a un canal.

 SUBSCRIBE CodigoFacilito

En este caso indicamos que el cliente se suscribe al canal CodigoFacilito. Estaremos a la escucha todos los mensajes de dicho canal.

Si todo funciona correctamente, obtendremos como resultado la siguiente salida.

1) "subscribe"
2) "CodigoFacilito"
3) (integer) 1

Perfecto, ahora, en otra ventana, ejecutamos los siguientes comandos.

Nuevamente nos autenticamos con el servidor.

./redis-cli 

A través del comando PUBLISH, seremos capaces de enviar un mensaje a todos los usuarios suscritos a un canal.

 PUBLISH CodigoFacilito "Hola Mundo!"

En este caso enviamos el mensaje "Hola mundo!" al canal CodigoFacilito.

Cómo nuestro primer cliente se encuentra suscrito a dicho canal, el mensaje debe visualizarse en consola.

1) "message"
2) "CodigoFacilito"
3) "Hola Mundo!"

Listo, con esto confirmamos que el mensaje fue enviado a todos los usuarios dentro del canal. En este caso solo tenemos un suscriptor, sin embargo podemos hacer la prueba con dos, cinco, diez o la n cantidad que deseemos.

Comunicación entre múltiples aplicaciones

Algo lo cual sin duda siempre me ha llamado mucho la atención, es el hecho de poder comunicar dos o más aplicaciones entre sí, y me refiero aplicaciones completamente diferentes, por ejemplo, quizás comunicar una aplicación C# que se ejecuta en Windows Server, con una aplicación en Go dentro de un contenedor en Ubuntu.

Formas de hacerlo hay muchas, no obstante para aplicaciones en tiempo real, utilizar PubSub sin duda será una de nuestras mejores opciones. 😎

Veamos un ejemplo de como podemos comunicar una script en Python con un programa en Go. Por supuesto nos estaremos apoyando de Redis.

En este caso, que les parece si el script en Python juega el rol de editor, enviando un mensaje sobre el canal, y el programa en Go jugará el Rol de subscriptor, obteniendo, e imprimiendo en consola todos aquellos mensajes del canal.

Publisher.

import redis

if __name__ == '__main__':
    channel = "CodigoFacilito"
    payload = "Hola mundo desde Python!"

    client = redis.StrictRedis(host='localhost', port=6379, db=0)
    client.publish(channel,  payload)

Subscriber.

package main

import (
    "log"
    "context"
    "github.com/go-redis/redis/v8"
)

var ctx = context.Background()

func main(){

    client := redis.NewClient(&redis.Options{
        Addr: "localhost:6379"  ,
        Password: "",
        DB: 0, 
    })

    _, err := client.Ping(ctx).Result()
    if err != nil {
        log.Println("No fue posible establecer la conexión!")
    }

    subscription := client.Subscribe(ctx, "CodigoFacilito")

    for {
        message, err := subscription.ReceiveMessage(ctx)
        if err != nil {
            panic("No fue posible leer el mensaje")
        }

        log.Println("Nuevo mensaje", message.Channel, message.Payload)

    }
}

Si ejecutamos tanto el script, como el programa, podemos percatarnos que la comunicación se realiza de forma exitosa. El programa en go puede leer lo que el script en Python envía. Este es un ejemplo muy sencillo, sin embargo dejame decirte que podemos enviar estructuras mucho más complejas a través de los canales, quizás un objeto JSON serializado. 🍻

Conclusión

Como pudimos observar la fácilidad con la cual podemos envíar, y recibir múlltiples mensajes, a través de múltiples usuarios y como estos no se encuentran limitados a la arquitectura o al lenguaje, es lo que hace de PubSub, junto con Redis, una de nuestras mejores opciones en cuanto a proyecto en tiempo real se refierén. Si bien es cierto exiten otras alternativas, creo, desde mi punto de vista, que en terminos de flexibilidad y perfomances, no hay comparación.