Aller au contenu

Vert.x

Un article de Wikipédia, l'encyclopédie libre.
Vert.x
Description de l'image Vert.x Logo.svg.

Informations
Développé par Tim Fox et les contributeurs du projet
Dernière version 4.5.11 ()[1]Voir et modifier les données sur Wikidata
Dépôt github.com/eclipse/vert.xVoir et modifier les données sur Wikidata
Écrit en Java, Javascript, Ruby, Python, Groovy, CoffeeScript, Clojure, Scala
Environnement JVM
Type Framework
Licences Apache Software Licence 2.0, Eclipse Public Licence
Site web vertx.ioVoir et modifier les données sur Wikidata

Eclipse Vert.x est un framework événementiel pour la JVM s'inspirant librement de Node.js. Il est publié en open source sous licences Apache Software Licence 2.0 et Eclipse Public Licence.

En particulier, Vert.x permet la création de serveurs web, permettant notamment une montée en charge très efficace[citation nécessaire]. Vert.x se pose ainsi en alternative aux conteneurs de servlets tel que définis dans la norme Java EE, comme Tomcat ou Jetty.

Vert.x peut également être embarqué comme une bibliothèque au sein d'une autre application Java.

Le , Vert.x a obtenu le prix de la technologie Java la plus innovante ("Most Innovative Java Technology") de l'année lors du salon JAX 2014 à Mayence[2].

Historique du projet

[modifier | modifier le code]

Vert.x (prononcé "Vertex") a été créé par Tim Fox en 2011 alors qu'il travaillait pour VMWare. Lorsqu'il a quitté cette société en pour travailler sur Vert.x chez Red Hat[3], VMWare détenait les droits sur le code écrit par Tim Fox, la marque Vert.x, le logo, ainsi que le groupe Google et le dépôt Github[4].

Après discussions, il a été décidé en janvier 2013 que le projet rejoindrait la fondation Eclipse[5]. Une proposition de projet a été créé dans ce sens et en , Vert.x est devenu un projet de la fondation Eclipse. Le projet est maintenant sous une double licence ASL et EPL[6]. Vert.x est désormais un sous-projet du projet RT (pour Runtime) de la fondation Eclipse[7].

Au sein de Red Hat, Tim Fox et Norman Maurer, les principaux contributeurs de Vert.x, ont rejoint Project:odd, un département de projets avancés.

Vert.x devait initialement s'appeler Node.x, en référence à Node.js et à son aspect polyglotte, mais les risques de conflit juridique avec Joyent, l'entreprise promouvant Node.js, ont finalement poussé à le renommer Vert.x.

La page de proposition sur le site d'Eclipse indique « environ 68 contributeurs » ayant déjà publié du code pour le projet Vert.x.

La version 2.1 a été publiée le [8]. Elle ajoute notamment le support de Clojure et de Scala.

La version 3.0 prévoit notamment le support du langage Ceylon (des exemples et de la documentation sont déjà disponibles sur le site, mais le module Ceylon n'est pas encore intégré à la distribution standard), le chiffrement du bus d'événements, la génération de données métriques permettant l'intégration à des systèmes de monitoring et la fourniture d'interfaces avec le bus d'événements pour Android et iOS, de manière similaire à l'interface pour client Javascript vertxbus.js.

Principes de fonctionnement

[modifier | modifier le code]

Comme Node.js, Vert.x est une implémentation du design pattern reactor. Le fonctionnement de Vert.x est basé sur un composant appelé verticle. Par défaut, chaque verticle n'est instancié qu'une seule fois par cœur d'exécution du système, mais il est possible d'augmenter le nombre d'instance pour une verticle, bien que ça ne soit pas recommandé. Chaque instance de verticle s'exécute toujours dans le même thread, mais un thread peut exécuter des verticles différents. Vert.x maintient un pool de threads, appelé "event loop pool" pour l'exécution des verticles. La taille du pool correspond par défaut à un seul thread par cœur physique disponible dans le système, ce qui veut dire que chaque cœur du système va exécuter un seul thread, ce qui permet une performance optimale en diminuant les pertes de puissance de calcul dues aux changements de contexte d'exécution des différents cœurs. Une verticle fonctionne avec une boucle événementielle (event loop en anglais) gérant une file de requêtes en entrée. Le rôle de cette boucle est de lire les requêtes et de les traiter de façon non-bloquante. Chaque verticle a son propre classloader, ce qui permet de s'assurer que les verticles ne peuvent pas connaitre l'état d'une autre verticle, même pour les attributs statiques.

Un type particulier de verticle, appelé working verticles, permet d'exécuter des traitements bloquants, ce qui permet des traitements longs et complexes, ainsi que l'utilisation d'outils traditionnels Java, n'ayant pas été conçus pour le traitement non-bloquant, comme JDBC, par exemple. Les working verticles peuvent s'exécuter dans plusieurs threads sur un même cœur, à la différence des autres verticles. Vert.x gère un pool de threads appelé "background pool" pour assigner des threads aux working verticles[9].

Les différents verticles disposent d'un espace de partage de données. Les données doivent toutefois être immuables.

Les verticles peuvent être écrits en Java, Javascript, CoffeeScript[10], Ruby, Python, Groovy, Scala et Clojure. Il est possible de combiner des verticles écrites dans différents langages au sein d'une même application. Le développement en Javascript suit le standard CommonJS.

Les verticles peuvent être lancés directement depuis la ligne de commande ou programmatiquement.

Vert.x peut communiquer en utilisant les protocoles TCP, HTTP et Websockets, y compris à travers un chiffrement SSL. Il peut aussi communiquer avec des applications Javascript en utilisant SockJS.

Le bus événementiel (Event bus) est le système de communication principal entre les verticles, chaque verticle étant isolée et n'ayant pas connaissance de l'existence des autres. Il est basé sur le principe du passage de messages. Ce bus permet la diffusion d'information suivant plusieurs patterns architecturaux : publication/souscription (un message est reçu par tous les abonnés), messagerie point à point (un seul abonné reçoit le message, et les différents abonnés reçoivent des messages à tour de rôle, suivant le principe du round-robin) et requête/réponse (comme le point à point, mais le message contient un handler de réponse). Le bus événementiel peut s'ouvrir sur des applications Javascript hors de Vert.x à l'aide d'un pont utilisant SockJS, en particulier vers des applications clientes, ce qui permet une communication utilisant des websockets, plus directe qu'avec des web services. L'application Javascript doit importer le fichier vertxbus.js afin de pouvoir accéder au bus de Vert.x. D'autres moyens d'accès à ce bus sont prévus pour la version 3 de Vert.x, notamment des bibliothèques C++, ainsi que pour Android et iOS.

Des verticles assurant une fonctionnalité précise peuvent être regroupés sous forme de module réutilisable. Ces modules peuvent ensuite être ajoutés dans un référentiel Maven ou sur Bintray.

Un mode haute disponibilité permet de faire en sorte qu'un verticle victime d'un plantage se relance sur un autre nœud du système ("automatic failover"). Il est aussi possible de regrouper les nœuds en groupe afin qu'un verticle se relance sur un nœud du même groupe. On peut également définir un "quorum" de nœuds devant fonctionner dans un groupe pour qu'un verticle puisse y être déployé.

Vert.x s'appuie sur Netty pour la couche réseau non-bloquante, sur Hazelcast pour l'espace mémoire partagé et sur Jackson pour la génération et le parsing JSON. Les couches permettant l'utilisation d'autres langages ont été écrites grâce à JRuby, Jython et Mozilla Rhino (JavaScript) et bien sûr Groovy, Scala et Clojure. Le moteur de production utilisé par le projet est Gradle et le code est outillé par des tests avec JUnit.

Voici de quelle manière il est possible d'écrire un verticle lançant un serveur web très simple permettant de servir un fichier statique, dans différents langages supportés par Vert.x.

Ceylon :

import io.vertx.ceylon.platform { ... }
import io.vertx.ceylon.core { ... }
import io.vertx.ceylon.core.http { ... }

shared class Server() extends Verticle() {
    start(Vertx vertx, Container container) => vertx.createHttpServer().requestHandler(
        void (req) {
            value file = req.path == "/" then "index.html" else req.path;
            req.response.sendFile("webroot/" + file);
        }
    ).listen(8080);
}

Clojure :

(ns example.server
  (:require [vertx.http :as http]))

  (-> (http/server)
    (http/on-request
      (fn [req]
        (let [uri (.uri req)]
          (-> req
            (http/server-response)
            (http/send-file (str "webroot/" (if (= "/" uri) "index.html" uri)))))))
    (http/listen 8080))

CoffeeScript :

vertx = require "vertx"

vertx.createHttpServer().requestHandler((req) ->
	file = if req.path == "/" then file="index.html" else req.path
  	req.response.sendFile "webroot/"+file
).listen 8080, 'localhost'

Groovy :

vertx.createHttpServer().requestHandler { req ->
   def file = req.uri == "/" ? "index.html" : req.uri
   req.response.sendFile "webroot/$file"
}.listen(8080)

Java :

import org.vertx.java.core.Handler;
import org.vertx.java.core.http.HttpServerRequest;
import org.vertx.java.platform.Verticle;

public class Server extends Verticle {
    public void start() {
        vertx.createHttpServer().requestHandler(new Handler<HttpServerRequest>() {
            public void handle(HttpServerRequest req) {
                String file = req.path().equals("/") ? "index.html" : req.path();
                req.response().sendFile("webroot/" + file);
            }
        }).listen(8080);
    }
}

Javascript :

load('vertx.js')

vertx.createHttpServer().requestHandler(function(req) {
   var file = req.path === '/' ? 'index.html' : req.path;
   req.response.sendFile('webroot/' + file);
}).listen(8080)

Python :

import vertx

server = vertx.create_http_server()

@server.request_handler
def handle(req):
    filename = "index.html" if req.uri == "/" else req.uri
    req.response.send_file("webroot/" + filename)
server.listen(8080)

Ruby :

require "vertx"

Vertx::HttpServer.new.request_handler do |req|
   file = req.uri == "/" ? "index.html" : req.uri
   req.response.send_file "webroot/#{file}"
end.listen(8080)

Scala :

vertx.createHttpServer.requestHandler { req =>
  val file = if (req.path == "/") "index.html" else req.path
  req.response.sendFile(s"webroot/$file")
}.listen(8080)

Extensibilité

[modifier | modifier le code]

La structure modulaire de Vert.x permet une très bonne extensibilité, et de nombreux modules proposant des fonctionnalités très variées sont déjà disponibles, proposant par exemple le support de langages supplémentaires, comme Ceylon ou PHP (en utilisant Quercus), des connecteurs pour des bases de données NoSQL comme MongoDB ou Redis, des connecteurs asynchrones pour des bases de données relationnelles comme MySQL ou PostgreSQL, des implémentations alternatives pour l'utilisation de Javascript (en utilisant DynJS ou Nashorn au lieu de Rhino), l'intégration avec des frameworks d'injection de dépendance comme Guice ou l'intégration de la bibliothèque de communication Socket.io. Des artefacts pour Maven et Gradle sont également disponibles.

L'équipe de développement Vert.x propose un catalogue des modules d'extension dans lequel chacun peut enregistrer un nouveau module[11].

Des surcouches spécialisées ont été publiées : Vertigo, permettant le traitement d'événements en temps réel, Nodyn, qui assure la compatibilité avec Node.js, Yoke pour faciliter l'utilisation de Vert.x comme un middleware web.

Références

[modifier | modifier le code]

Articles connexes

[modifier | modifier le code]

Liens externes

[modifier | modifier le code]