VT2018 Thorntail

From air
Jump to navigation Jump to search

Introduction

Technologie : Thorntail
Auteur : CHANET Zoran
E-mail : zoran.chanet@etu.univ-grenoble-alpes.fr
Presentation : Transparents
Démonstration : Démo

Résumé

Anciennement nommée Wildfly Swarm (jusqu'en juin 2018), en référence au serveur d'application Java Entreprise Edition Wildfly proposé par RedHat, Thorntail permet la décomposition dudit serveur afin d'en emporter uniquement les parties nécessaires à votre API. Thorntail permet donc de créer des applications microservices légères et facilement déployables. Chaque service est paqueté dans son propre UberJAR, emportant avec lui toutes ses dépendances, et uniquement les dépendances nécessaires. Une fois empaquetés, ces UberJAR sont déployables sur tout serveur d'application compatible JEE. Thorntail brille également par sa simplicité : les prérequis à son utilisation se limitent à la version JDK8 de JEE, et la version 3.2.5 de Maven, et sa mise en place se fait uniquement à travers le fichier pom.xml de l'architecture Maven.

Abstract

Formerly known as Wildfly Swarm (until June 2018), refering to the Wildfly Java Entreprise Edition application server offered by RedHat, Thorntail splits the server to take just enough of the server to run your API. Thorntail thus allows to create easily-deployable lightweight microservices applications. Each service is packaged into its own UberJAR, containing every required dependency, and only the required dependencies. Once packaged, the UberJAR can be deployed to any JEE-compatible application server. Another Thorntail benefit is its simplicity: the only prerequisites are JEE JDK8 and 3.2.5 Maven, and putting it in place only requires some addings to the Maven's architecture's pom.xml.

Synthèse

Prérequis

Description

fig.1 : Aperçu de Wildfly
fig.2 : Aperçu de Thorntail

Thorntail, précédemment connue sous le nom de Wildfly Swarm, est une initiative de RedHat. Cette technologie fait suite au serveur d'application WildFly, également proposé par RedHat. Le but premier de Thorntail est de permettre un packaging plus léger pour les applications ne nécessitant pas la totalité des options embarquées sur le serveur WildFly (voir fig.1). Si par exemple l'application déployée ne nécessite l'utilisation que de JAX-RS, alors son architecture pourra être allégée, comme le montre la fig.2. Le changement de nom opéré lors de la release du 27 Juin 2018 (comme annoncé dans le blog de thorntail) n'est pas anodin. Il fait suite l'indépendance grandissante avec le serveur Wildfly.
Par construction, Thorntail est donc une technologie fortement orientée microservices. En effet, puisqu'il devient permis d'emporter uniquement les services nécessaires il semble logique d'isoler des services, les déclarant comme des applications séparées embarquant chacune le strict nécessaire à son fonctionnement. C'est grâce à ce mécanisme que Thorntail offre des conteneurs légers et facilement déployables. Le déploiement de ces conteneurs n'est pas limité au serveur d'application Wildfly, ils sont déployable par tous les moyens classiques (e.g. docker), et sur tout serveur d'application compatible JEE.
Thorntail se base fortement sur la technologie Maven. Par exemple, l'utilisation de Thorntail dans un projet se définit par l'ajout dans le pom.xml du projet de quelques lignes (décrites dans les sections suivantes). De plus, Thorntail fait usage d'une fonctionnalité de Maven ancienne mais peu répandue, le BOM (Bill Of Material, décrit dans les sections suivantes).
Enfin, Thorntail se base sur la version JEE de Java, utilisée pour les applications coté serveur. Ceci ajouté à la facilité de création d'une architecture microservices, la compatibilité avec Microprofile (qui optimise le JEE pour les architectures microservices) se fait une évidence.

Mise en place

La mise en place de Thorntail dans un projet se fait par l'intermédiaire du fichier pom.xml du projet. Une fois les lignes données dans les sections Plugin, BOM et Fractions ajoutées dans le fichier, il suffit de lancer la commande donnée dans la section Génération pour compresser l'application (ou le service) en un UberJAR. Cet UberJar est donc le fichier JAR qui devra être déployé. Une commande Maven, également décrite dans la section Génération, permet de générer l'UberJAR et le déployer en local. L'application (ou le service) sera alors déployé en localhost sur le port 8080.

Plugin

pom.xml :

<plugin>
  <groupId>io.thorntail</groupId>
  <artifactId>thorntail-maven-plugin</artifactId>
  <version>${version.thorntail}</version>
  <executions>
    <execution>
      <goals>
        <goal>package</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Ces quelques lignes permettent d'ajouter au projet le plugin io.thorntail (ligne 2) pour Maven. Ce plugin permet à Maven de gérer le packaging comme le requiert Thorntail (ligne 8), mais aussi la gestion des fractions, concept essentiel à Thorntail décrit dans la section dédiée. Le détail de ce plugin peut bien sûr être observé dans le repository Maven.

BOM

pom.xml :

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>io.thorntail</groupId>
      <artifactId>bom</artifactId>
      <version>${version.thorntail}</version>
      <scope>import</scope>
      <type>pom</type>
    </dependency>
  </dependencies>
</dependencyManagement>

Voici les lignes permettant l'import de la dépendance BOM (Bill Of Materials). Le concept de BOM pour Maven repose sur la notion de scope import (ligne 7). Le scope import permet de remplacer la dépendance le déclarant (ici lignes 3 à 9) par la section dependecyManagement du pom auquel on fait référence (ici, le bom du groupe io.thorntail, lignes 4 et 5). À la lecture du pom.xml du projet, cette dépendance sera donc remplacée par le contenu du BOM.
Nous revenons donc à la définition du BOM. Un BOM est simplement un pom (comme indiqué ligne 8) qui ne contient que la section dependencyManagement, rassemblant les versions des dépendances qui seront utilisées dans les projets, permettant aux utilisateurs de Thorntail de s'affranchir de la gestion des versions des différentes fractions auxquelles ils feront appel.

Fractions

pom.xml :

<dependency>
  <groupId>io.thorntail</groupId>
  <artifactId>jaxrs</artifactId>
</dependency>

Nous voici venu au concept de fractions, essentiel à Thorntail. Une fraction n'est autre qu'un module, originalement un morceau tiré du serveur Wildfly, servant un but précis. En reprenant les figures 1 et 2 de la section Description, nous voyons (fig.1) que le serveur Wildfly implémente un certain nombre de fonction, JAX-RS, EJB3, Transactions, CORBA et Batch. Une fraction correspond simplement à l'extraction de l'une de ces fonctions. De toutes les fractions pouvant être extraites de la fig.1, l'application décrite par la fig.2 ne nécessite (et donc n'emporte) que la fraction JAX-RS.
Il suffit donc de déclarer dans le pom.xml une dépendance par fraction nécessaire (en remplaçant jaxrs par le nom de la fraction, ligne 3). Grâce à la référence au BOM décrite dans la section précédente, nous pouvons faire fi des versions.

Génération

fig.3 : Nommage des JAR par contenu

Packaging :

mvn package

Execution :

java -jar <myapp>-thorntail.jar

Packaging + Execution :

mvn thorntail:run

Le packaging effectué par Thorntail va produire un UberJAR, contenant donc les composants de l'application, ses dépendances, ainsi que les composants runtime de l'application (le serveur d'application, en quelque sorte). Un tel packaging permet la production d'un exécutable binaire unique, très pratique en cas d'Intégration Continue et Déploiement Continu. Cela permet aussi, dans le cadre d'une application microservice, que chaque service soit fortement indépendant, emportant avec lui ses dépendances et ses composants runtime. Un autre avantage des UberJAR est qu'ils sont avant tout des JAR, et peuvent donc être exécutés comme tout JAR.
Thorntail permet également la production d'HolloJAR, n'emportant que les composants runtime, dans le but par exemple d'un déploiement en containers avec Docker, de placer l'image des composants runtime à un niveau différent des composants de l'application, qui sont modifiés plus souvent.
À des fins de test et de développement, il est donc possible d'exécuter l'UberJAR généré, qui sera déployé localement, exposant l'API produite.

Efficacité

Sur l'exemple de la démonstration, une construction classique (utilisant JBoss) crée un fichier .war d'une taille de 6,2kb, alors qu'une construction utilisant thorntail crée un fichier .war d'une taille de 4,2kb. Cependant, il s'agit d'un exemple de petite taille, et l'écart se creuse pour des exemples plus conséquents faisant appel à de plus nombreuses fonctionnalités.

Sources