Real Time Web Applications con Vert.x

Las aplicaciones web de hoy en día están vivas. Facebook, Gmail, diversos servicios de chat y tableros de cotizaciones nos dan la información que queremos, cuando lo requerimos. Esto es posible gracias a los nuevos estándares web, cada vez más redes de alta velocidad, y la multitud de nuevas categorías de dispositivos de smartphones a los televisores inteligentes.
Para construir estos nuevos tipos de aplicaciones, también necesitamos nuevo tipo de tecnología. Los frameworks web que alimentan gran parte de la web, no fueron pensados o diseñados necesariamente para servir en tiempo real. Aquí es donde entra Vert.x, el cual ha sido pensado desde la base para que pueda construir aplicaciones web escalables en tiempo real.

¿Por qué Vert.x? 

Hay muchas técnicas y tecnologías que se podrían emplear para desarrollar aplicaciones web en tiempo real. Desde Node.js y Meteor a EventMachine de Ruby, y el apoyo WebSocket en Java EE 7, los desarrolladores de aplicaciones tienen un abundante abanico de opciones. Sin embargo, Vert.x proporciona una combinación única de cualidades que hace que sea una opción muy atractiva.

Vert.x es una plataforma de aplicaciones políglota, sin bloqueo (non-blocking), basada en eventos que se ejecuta sobre una  JVM (Java Virtual Machine).

Algunos de los puntos clave incluyen:

  • Políglota. Sus componentes de aplicaciones pueden ser escritos en JavaScript, Ruby, Groovy, Java o Python, y a la vez mezclar y combinar varios lenguajes de programación en una sola aplicación.
  • Modelo de concurrencia simple actor (actor-based systems, como es Akka). Vert.x permite escribir todo el código  de modo single threaded, es decir ejecutado por un único hilo a la vez, liberándonos de muchas de las dificultades de la programación multi-hilo. (No más sincronizaciones, volátil o bloqueo explícito).
  • Vert.x se aprovecha de la JVM y escala de manera transparente sobre los núcleos del CPU disponibles sin tener que bifurcar manualmente múltiples servidores y manejar la comunicación entre procesos.
  • Vert.x tiene un modelo de programación simple, asíncrono para escribir aplicaciones escalables no bloqueantes que pueden escalar a 10s, 100s o incluso millones de conexiones simultáneas utilizando un número mínimo de hilos del sistema operativo.
  • Vert.x incluye un bus de eventos distribuido que se extiende por el lado del cliente y el servidor por lo que sus componentes de aplicaciones se pueden comunicar fácilmente. El bus de eventos incluso penetra en en el navegador con JavaScript que permite crear aplicaciones web en tiempo real sin esfuerzo.
  • Vert.x ofrece verdadero poder y simplicidad, sin ser simplista. La configuración y el código duplicado se mantienen a un mínimo.
  • Vert.x incluye un sistema de módulos de gran alcance y de registro módulo público, por lo que se puede reutilizar y compartir fácilmente los módulos Vert.x con otros.
  • Vert.x puede ser embebido en sus aplicaciones Java existentes.

Conceptos en Vert.x
En esta sección vamos a dar una visión general de los principales conceptos en Vert.x.

Verticle

  • Los paquetes de código que Vert.x ejecuta  se llaman verticles (pensar en una partícula, por Vert.x).
  • Verticles pueden ser escritos en JavaScript, Ruby, Java, Groovy o Python (Scala y Clojure están en producción).
  • Muchos verticles pueden estar ejecutándose simultáneamente en la misma instancia Vert.x.
  • Una aplicación puede estar compuesta de múltiples verticles desplegados en los diferentes nodos de la red de comunicación mediante el intercambio de mensajes a través del bus de eventos Vert.x.
  • Para aplicaciones triviales las verticles se pueden ejecutar directamente desde la línea de comandos, pero más generalmente se empaquetan en módulos.

Módulo

  • Las aplicaciones Vert.x se componen generalmente de uno o más módulos. Los módulos pueden contener múltiples verticles, potencialmente escritos en diferentes idiomas. Los módulos permiten encapsular y reutilizar funcionalidades.
  • Los módulos se pueden colocar en cualquier repositorio Maven o Bintray, y ser registrados en el registro de módulos de Vert.x.
  • El sistema de módulos Vert.x permite un ecosistema de módulos Vert.x gestionados por la comunidad Vert.x.

Instancias Vert.x

  • Las Verticles se ejecutan dentro de una instancia Vert.x. Una sola instancia Vert.x corre dentro de su propia instancia de la JVM. Pueden haber muchas verticles ejecutándose dentro de una única instancia Vert.x en cualquier momento.
  • Pueden haber muchas instancias Vert.x ejecutándose en el mismo host, o en diferentes máquinas de la red al mismo tiempo. Los instancias se pueden configurar para agruparse entre sí formando un bus de eventos distribuidos sobre el cual las instancias verticle pueden comunicarse.

Políglota

  • Vert.x permite escribir verticles en JavaScript, Ruby, Java, Groovy y Python y el objetivo es apoyar Clojure y Scala en poco tiempo. Estas verticles pueden interoperar sin problemas con otras verticles independientemente del lenguaje en que están escritas.

Concurrencia

  • Vert.x garantiza que una instancia de verticle particular nunca es ejecutado por más de un hilo al mismo tiempo. Esto le da una gran ventaja al desarrollador, ya que se puede programar todo el código como un solo hilo.
  • Si estás acostumbrado a la concurrencia multi-hilo tradicional esto puede ser un alivio ya que no se tiene que sincronizar el acceso. Esto significa que las condiciones de carrera desaparecen, y los abrazos mortales sin salida son una cosa del pasado.
  • Diferentes instancias de verticles se comunican entre sí a través del bus de eventos mediante el intercambio de mensajes. Las aplicaciones Vert.x son concurrentes porque hay varias instancias verticle de un solo hilo ejecutándose simultáneamente y enviándose mensajes el uno al otro.
  • Como tal, el modelo de concurrencia Vert.x asemeja al Modelo Actor donde las instancias verticle se corresponden con actores. Hay sin embargo diferencias, por ejemplo, las verticles tienden a ser de grano más grueso que los actores.

Modelo de programación asíncrona

  • Vert.x proporciona un conjunto de APIs básicas asíncronos. Esto significa que la mayoría de las cosas que haces en Vert.x implican el establecimiento de los controladores de eventos. Por ejemplo, para recibir datos de un socket TCP se establece un manejador – el controlador se llama entonces cuando llegan datos.
  • También establece manejadores para recibir mensajes desde el bus de eventos, para recibir las solicitudes y respuestas HTTP, para ser notificado cuando se cierra una conexión, o para ser notificado cuando se dispara un temporizador. Este es un patrón común en toda la API Vert.x.
  • Utilizamos una API asíncrona para que podamos escalar para manejar muchas verticles utilizando un pequeño número de hilos del sistema operativo. De hecho Vert.x establece el número de hilos igual al número de núcleos disponibles en la CPU. Con una aplicación perfectamente no bloqueante nunca se necesitarán más hilos que esos.
  • Con un API síncrona tradicional, los hilos se bloquean en operaciones del API, y mientras están bloqueados no pueden hacer ningún otro trabajo. Un buen ejemplo es un bloqueo de lectura de un socket, mientras el código está a la espera de recibir datos del socket no puede hacer otra cosa. Esto significa que si queremos apoyar a 1 millón de conexiones simultáneas (no es una idea descabellada para la próxima generación de aplicaciones móviles), entonces necesitaríamos 1 millón de hilos. Este enfoque claramente no escala.
  • Las API asíncronas son a veces criticadas por ser difícil de desarrollar, sobre todo cuando hay que coordinar resultados desde más de un manejador de eventos.
  • Hay maneras de mitigar esto, por ejemplo, mediante el uso de un módulo como mod-rx-vertx que permite componer flujos de eventos asíncronos de una manera poderosa. Este módulo utiliza la biblioteca RxJava que se inspira de net «extensiones reactivas».

Loops de eventos

  • Internamente, una instancia Vert.x gestiona un pequeño conjunto de hilos, coincidiendo el número de hilos con los núcleos disponibles en el servidor. Llamamos a estos hilos bucles de eventos, debido a que iteran constantemente para ver si hay algún evento para entregar y si es así, entregarlo al controlador apropiado. Ejemplos de eventos podrían ser datos que han sido leídos de un socket, un temporizador que ha disparado, o una respuesta HTTP que ha terminado.
  • Cuando una instancia verticle estándar es desplegada, el servidor elige un bucle de eventos (hilo) que se asignará a dicha instancia. Cualquier trabajo posterior que se haga para esta instancia siempre será enviado usando exactamente ese mismo hilo. Por supuesto, ya que existen potencialmente muchos miles de verticles que se ejecutan en un momento dado, un solo bucle de eventos será asignado a muchos verticles al mismo tiempo.
  • A esto se le llama el modelo multi-reactor. Es como el patrón del reactor, pero hay más de un bucle de eventos.

La Regla de Oro – No bloquee el bucle de eventos!

  • Un bucle de eventos en particular es potencialmente utilizado para dar servicio a muchas instancias verticle, por lo que es fundamental que no se bloquee en la ejecución de un verticle. Si bloquea significa que no puede entregar eventos a cualquier otro manejador, y la aplicación se detendrá.
  • El bloqueo de un bucle de eventos significa atarlo a un verticle y no permitirle que continúe rápidamente para manejar otros eventos, lo que incluye:
  1. Thread.sleep ()
  2. Object.wait ()
  3. CountDownLatch.await () o cualquier otro bloqueo que opera desde java.util.concurrent.
  4. Iterando en un bucle
  5.  Ejecución de una operación computacionalmente intensivas de larga duración – procesamiento de números.
  6.  Llamar a una operación de bloqueo de la biblioteca de terceros que podrían tomar algún tiempo para completar (por ejemplo, la ejecución de una consulta JDBC)

Escribir código de bloqueo – introducir Trabajador Verticles

  • En un verticle normal nunca se debe bloquear el bucle de eventos, sin embargo, hay casos en los que realmente no se puede evitar el bloqueo, o que realmente tienen operaciones computacionalmente intensivas a realizar. Un ejemplo sería llamar a un tradicional API Java como JDBC.
  • También puede ser que se desee escribir código de bloqueo de estilo directo, por ejemplo, si desea escribir un servidor web simple, pero se sabe que no va a tener una gran cantidad de tráfico y no es necesario para escalar a muchas conexiones.
  • Para casos como estos, Vert.x le permite marcar una instancia verticle particular como un verticle trabajador. Un trabajador verticle difiere de una verticle estándar en que no se asigna un hilo bucle de eventos Vert.x, sino que se ejecuta en un hilo de un pool de hilos interno llamada worker pool.
  • Como las verticles estándar, las verticles trabajadoras nunca se ejecutan simultáneamente por más de un hilo, pero a diferencia de verticles estándar pueden ser ejecutadas por diferentes hilos en diferentes momentos – mientras que un verticle estándar siempre es ejecutado por el mismo hilo exacta.
  • En un verticle trabajador es aceptable realizar operaciones que puedan bloquear el hilo.
  • Mediante el apoyo de ambos verticles, el estándar (no bloqueante) y el trabajador (pudiendo ser bloqueante), Vert.x ofrece un modelo de hilos híbrido para que se pueda utilizar el enfoque apropiado para una aplicación. Esto es mucho más práctico que las plataformas que exigen bloquear, o no bloquear siempre.
  • Debe tenerse cuidado al usar verticles trabajadores ya que un enfoque de bloqueo no escala si se quiere tratar con muchas conexiones concurrentes.

Los datos compartidos

  • El paso de mensajes es muy útil, pero no es siempre el mejor enfoque para la concurrencia de todos los tipos de aplicaciones. Algunos casos de uso están mejor resueltos proporcionando estructuras de datos compartidos que se puede acceder directamente por diferentes instancias verticle en la misma instancia Vert.x.
  • Vert.x proporciona un mapa compartido y facilidad conjunto compartido. Insistimos en que los datos almacenados son inmutables con el fin de evitar condiciones de carrera que podrían ocurrir si se permite el acceso simultáneo a datos compartidos.

Vert.x API

  • Vert.x proporciona un conjunto pequeño y bastante justo de APIs que pueden ser llamados directamente desde verticles. Proporcionamos los APIs en cada uno de los idiomas que Vert.x apoya.
  • Prevemos que la API Vert.x no va a cambiar mucho con el tiempo y la nueva funcionalidad será añadida por la comunidad y el equipo central Vert.x en forma de módulos que se pueden publicar y re-utilizados por cualquier persona. Esto significa que el núcleo Vert.x puede permanecer muy pequeño y compacto, y sólo instalar los módulos adicionales que usted necesita para su uso.
  • Las APIs Vert.x se pueden dividir en la API de contenedores y la API del núcleo

API Contenedor

  • Esta es la opinión de la verticle del contenedor Vert.x en el que se está ejecutando. Contiene las operaciones para hacer cosas como:
  1. Desplegar y remover verticles
  2. Despegar y remover módulos
  3. Recuperar configuración de una verticle
  4. Inicio de sesión

API Core

  • Esta API proporciona funcionalidad para:
  1. Servidores y clientes TCP / SSL
  2. Servidores y clientes HTTP / HTTPS
  3. Servidores y clientes Websockets
  4. El bus de eventos distribuidos
  5. Temporizadores periódicos y puntuales
  6. Buffers
  7. Control de flujo
  8. Acceso del sistema de archivos
  9. Mapa compartido y conjuntos
  10. Acceso a la configuración
  11. SockJS

Código con ejemplos

Ejemplos vertx vertx-websocket-chat

Ejemplos varios

Módulo Vertx para persistir en couchbase

Enlaces externos de interés

Sitio oficial

Entrevista con el foundador de Vert.x

Comparación con Nodejs

Conferencia de Tim Fox en JAX

Tags

Access top talent now!

Related

Get in Touch