OSGi, quel avenir au niveau des applications?

Publié le Mis à jour le

Une nouvelle technologie est en phase de s’imposer comme standard au niveau des serveurs d’application, il s’agit de OSGi. Cette technologie permet de gérer au sein d’une même machine virtuelle les problématiques de chargement / déchargement dynamique de code, déploiement dynamique (et sans interruption) d’applications, gestion du versionning (et résolution des dépendances) des applications ainsi que des services.

Historique

Fondé en 1999, l’OSGi Alliance est un consortium industriel qui à l’origine avait pour intention de définir des spécifications ouvertes pour développer et déployer des services sur des systèmes embarqués. Très vite, le périmètre d’application s’est élargi vers les marchés de la sécurité, de l’automobile.
L’intégration d’Equinox au sein de l’écosystème Eclipse motive la communauté open source. Depuis cette dernière année, OSGi est en train de s’imposer côté serveur.

Technologie OSGI

Le choix de java remonte à la création du consortium. En effet, les caractéristiques de la JVM et du langage interdisent certaines pratiques dangereuses tels que les pointeurs, les dépassements de buffer…
La technologie OSGi est une plateforme orientée services de déploiement et d’exécution de services Java. Cette technologie est en phase de devenir un standard pour le déploiement, l’administration et l’exécution d’applications java grâce à la publication des JSR 277 (Java Module System), JSR 291 (Dynamic Component Support for Java SE) et JSR 294 (Improved Modularity Support in the Java Programming Language).

Description de l’architecture

Les applications au sein du framework OSGi collaborent par le biais de services. La plateforme met à disposition un registre de services (recherche, notification des changements, etc.).

Une application OSGi est composée des éléments suivants:

  • Bundles: unités de déploiement des composants fournissant les services
  • Services: Services exposés et un ensemble de propriétés typées
  • Framework ou conteneur: environnement d’exécution des bundles

Bundle:
L’unité de déploiement versionnée de la plateforme OSGi est le bundle. Il se présente sous la forme d’un jar contenant du code binaire ainsi que d’autres ressources (exécutable, image …). Les propriétés du bundle sont définies au niveau du fichier manifest du jar :

  • Bundle-ManifestVersion: Version du fichier MANIFEST.
  • Bundle-Name: nom du bundle.
  • Bundle-SymbolicName: nom symbolique du bundle.
  • Bundle-Version: numéro de version du bundle.
  • Bundle-RequiredExecutionEnvironment: environnement d’exécution requis.
  • Import-Package: « packages » importés ainsi que les numéros de versions requis.
  • Export-Package: « packages » exportés.
  • Bundle-Vendor: fournisseur du bundle.
  • DynamicImport-Package (à partir de la version 3 des spécifications): dépendances importées dynamiquement (patron de package attendu). Ces dépendances ne doivent pas être obligatoirement disponible lors du démarrage du bundle. Ce type d’import est intéressant pour la mise en place de plugin.
  • Bundle-NativeCode: Liste des bibliothèques natives utilisées.
  • Require-Bundle: Identifiant des bundles nécessaires.
  • Bundle-Activator: nom du bundle Activator permettant d’exécuter des traitements au démarrage et à l’arrêt du bundle. Cette classe livrée avec le bundle doit implémenter l’interface BundleActivator.
  • Bundle-Classpath: classpath nécessaire pour l’exécution du bundle.

Le cycle de vie d’un bundle est le suivant:

Les bundles sont administrés via une interface locale ou distante cette dernière permet:

  • l’installation/désinstallation de bundles.
  • de démarrer/arrêter les bundles.
  • de monter en version les bundles.
  • de visualiser le statut des bundles.

Un composant OSGi (bundle) peut importer/exporter des packages ainsi qu’exposer / consommer des services.

Package
L’entité de partage du code (partage des classes) est le package, chaque package est versionné. Les packages ni importés ni exportés ont uniquement une portée locale au niveau du bundle (notion de namespace). Afin de pouvoir mettre à jour un package (l’exporter) sans impacter les utilisateurs, il faut conserver une compatibilité ascendante entre les versions.

Service
Les implémentations du service sont définies au niveau du bundle. Les consommateurs de ce dernier n’ont connaissance que de l’interface. Lors de son enregistrement un service est caractérisé par son nom, son emplacement, son numéro de version ainsi que par un ensemble de propriétés typés. Ainsi par exemple le consommateur du service pourra effectuer la recherche du service d’impression ayant la caractéristique noir et blanc ou bien couleur.

Activator
Le paramètre d’entré Bundle-Activator du fichier manifest du jar désigne la classe servant de point d’entrée lors de l’activation ou de l’arrêt du bundle. En général, le rôle de cette instance est de gérer les services consommés et/ou publiés.

public class Activator implements BundleActivator // package importé
private final Printer printer = new Printer("==> ");
private ServiceRegistration reg=null;
// service exposé
private PrinterService service =null;
// service consommé
private PaymentService payService = null;
private ServiceReference ref = null;
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
this.printer.print("Start Bundle...");
service = new PrinterServiceImpl();
// propriétés typées du service
Dictionary props=new Properties();
props.put("color", false);
// enregistrement du service
reg=context.registerService(
service.getClass().getName(), service, props);
// recherche d'un service de paiement
ServiceReference[] refs=context.getServiceReferences
("com.bank.PaymentService","(bank=myBank)");
if(refs!=null && refs.length > 0) {
ref = refs[0];
// récupération du service
payService = (PaymentService) context.getService(ref);
// appel de la méthode
payService.pay();

}
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception this.printer.print("Stop Bundle ...");
// effacer le service du registre
reg.unregister();
if(ref != null) {
// liberation de l'instance
payService = null;
// libération du service
context.ungetService(ref);

}
}

Exemple d’utilisation de OSGI à l’heure actuelle

  • Le noyau de l’ESB Apache ServiceMix est basé sur la plateforme OSGI.
  • Le serveur d’application JOnAS 5 est implémenté autour d’une architecture orientée service basée sur OSGi. Cette approche leur permet de fournir un serveur d’application modulable dynamiquement (au runtime).
  • Depuis sa version 3 Eclipse embarque une plateforme OSGi afin de pouvoir charger/décharger les plugins dynamiquement et non plus au démarrage de l’IDE. Les plugins eclipse sont donc des bundles OSGi. Le conteneur OSGi utilisé par eclipse est Equinox.

L’utilisation de OSGi offre de nombreux avantages:

  • amélioration de la qualité de service en autorisant la publication de correctifs à chaud. Mais aussi en offrant la possibilité de monter en version dynamiquement.
  • possibilité de déployer dynamiquement de nouveaux modules
  • cohabitation de plusieurs versions d’un service.
  • redéployer à chaud le même service avec plus de traces pour résoudre un problème en production

Conteneur OSGI / Framework OSGi

Implémentation Open source:

  • Felix: Félix est un projet incubé par la plateforme apache. Ils œuvrent actuellement pour être compatible à 100% avec la version 4 des spécification: OSGi R4 Service Platform
  • Oscar: La version de production stable actuelle d’Oscar est la 1.0.5. De nombreux bundles sont disponible sur le site via OBR
  • Knopflerfish: La version courante est la version 2.5

Conclusion

L’utilisation de OSGi au niveau des serveurs (serveurs d’application, bus …) est une tendance forte à l’heure actuelle. Cependant, OSGi commence tout juste à faire son apparition au niveau des applications via l’arrivée de Spring Dynamic Module ou encore d’un plugin OSGi pour Struts 2. La réalisation d’applications autour d’un noyau OSGi apporte un réel gain aussi bien en terme de conception (faible couplage et forte cohérence des modules grâce aux services) qu’en terme de robustesse et qualité de service (possibilité d’intervenir à chaud). De plus, le noyau OSGi étant léger et nécessitant peu de ressources aura très peu d’impact sur les performances de l’application (empreinte mémoire, utilisation CPU). Les applications étant de plus en plus architecturées en couches, composants et services; l’utilisation d’OSGi devrait se démocratiser au niveau d’applicatifs ayant de fortes contraintes de qualité de service et de robustesse.

Des réflections sont actuellement en cours pour rendre disponible la technologie OSGi sous d’autres plateformes:

  • PHP: [http://garycourt.com/blog/post/php-osgi-framework-concept/->http://garycourt.com/blog/post/php-osgi-framework-concept/]
  • .NET: [http://www-adele.imag.fr/Les.Publications/intConferences/CCNC2006Esc.pdf<->http://www-adele.imag.fr/Les.Publications/intConferences/CCNC2006Esc.pdf]

  • Eclipse

  • Java, JEE

  • SOA

  • Standard