mardi 21 juin 2016

Développez facilement des services Windows configurables et robustes avec SystemHell

Si le monde informatique est plein de logiciels qui sont en interaction direct avec l’utilisateur, d’autres types de programmes s’exécutent dans l’ombre et permettent le bon fonctionnement de plusieurs services indispensables.

Ces logiciels fantômes qui servent à traiter vos mails, acheminer vos documents vers une imprimante, lancer des sauvegardes automatiques et bien d’autres choses sont appelés dans le jargon informatique des « démons systèmes ». Ils travaillent en arrière-plan et ont pour vocation à faire des traitements critiques, il est donc primordial que ceux-ci soient les plus robustes possibles.

Or, la plupart du temps, les concepteurs de ces programmes n’appliquent pas les bonnes pratiques comme ils pourraient le faire avec des logiciels de gestion traditionnels, et ce pour plusieurs raisons :
  • Les programmeurs travaillent souvent seul sur un démon système
  • Le .NET framework fourni des API natives très peu adaptées à la mise en place de design SOLID
  • Les démons systèmes sont (de premier abord) des programmes simples qui ne font que des choses répétitives.
De plus, il n’existe pas vraiment de bonnes pratiques quant à l’exploitation d’un démon système, ainsi chaque programmeur y va de sa créativité (enregistrement de logs dans des fichiers ou dans l’observateur d’événements, interface de contrôle obscure, configuration sous forme de fichier XML, INI ou base de registre, suivi des opérations à travers un fichier de sortie, …)

Tout cela peut rendre complétement fou ceux qui sont chargés d’installer, configurer et maintenir ces programmes, c’est pourquoi j’ai créé « SystemHell », un Framework Open Source permettant de mettre au point rapidement et facilement des services systèmes (démons) en .NET, avec l’avantage de donner plus de souplesse aux administrateurs pour les installer, les configurer et les maintenir.

Nous allons voir ensemble comment manipuler cet outil pour mettre sur pied des démons avec une vraie qualité professionnelle.


Principes de base


Un service système est un programme qui tourne en arrière-plan et qui doit être enregistré dans le SCM (Service Control Manager).

Service Control Manager
De ce fait, celui-ci est soumis à plusieurs contraintes :
  • Aucune interface graphique ou console de sortie ne permet de savoir ce que fait le service, à moins que le développeur n’en n’ait créé une adéquate.
  • Aucune norme ou principe ne fait foi pour installer ou configurer un service. Il existe donc une multitude de façon de faire ce qui complexifie la tâche des administrateurs.
  • Le débogage d’un service nécessite de s’attacher au processus pour pouvoir naviguer dans le code, ce qui s’avère très contraignant au quotidien.
Pour répondre à toutes ces problématiques, j’ai passé plusieurs mois à tester et sélectionner les outils et méthodes les plus simples qui formeront la base de l’interaction d’un démon développé avec SystemHell. Voici le résultat de cette réflexion :

En ce qui concerne l’interface graphique, le développeur doit disposer d’une fonction simple pour indiquer les informations qu’il désire présenter, et l’administrateur système doit pouvoir facilement disposer de ces informations pour les manipuler à sa convenance (recherche, enregistrement, filtrage, …)

Mon choix s’est donc porté sur l’outil DbgView (https://technet.microsoft.com/en-us/sysinternals/debugview.aspx) qui possède selon moins 3 avantages majeurs :
  • Le premier est sa taille : l’exécutable ne fait que 287Ko et ne nécessite aucune installation préalable. C’est donc un outil idéal pour accompagner un package de déploiement.
  • Le second est le nombre de possibilités que celui-ci a à offrir : Il permet de visualiser le flux d’informations comme dans un shell, d’appliquer des couleurs, des filtres, d’enregistrer les données selon une politique d’archivage, …
  • Le troisième est la simplicité d’utilisation pour le développeur : DbgView utilise le principe de l’OutputDebugString qui permet d’écrire dans un output spécifique à Windows les informations de debugging. Grace à ce mécanisme, un développeur n’a qu’à appeler la commande Trace.WriteLine pour afficher ses informations, sans se soucier des problèmes de concurrences d’accès.
En ce qui concerne les normes et principes qui permettent d’installer ou de configurer un service, mes choix se sont portés sur deux techniques :
  • Pour l’installation et la désinstallation, j’ai décidé de passer par l’outil sc.exe plutôt que par le couple classe d’installation / installutil.exe, car cela est d’une part beaucoup plus simple pour le développeur, et d’autre part beaucoup plus flexible pour l’administrateur. De plus, sc.exe étant disponible sur toutes les machines, un développeur peut aisément créer un outil d’installation qui se base sur celui-ci.
  • Pour la configuration du service, celle-ci se fera sans surprise par l’intermédiaire d’un fichier XML. Mais attention, le .NET Framework préconise de passer par un fichier de type app.config en utilisant les API qui vont avec, ceci ne sera pas du tout notre cas !
Quant à la problématique liée au débogage, SystemHell étant faiblement couplé avec les librairies qui feront office de démon, le développeur peut facilement utiliser toutes les méthodes de développement moderne (Test Driven Development, Behavior Driver Development, Domain Driven Design, architecture SOLID, …) afin de concevoir un système extrêmement robuste qui évitera de s’attacher à un processus externe lors de sa mise au point.

Fonctionnement de SystemHell


SystemHell.exe est un programme hôte qui s’exécute en tant que service système, et qui est capable de faire tourner un ou plusieurs démons dans leur propre contexte d’exécution.

Il peut donc faire tourner plusieurs démons différents ainsi que plusieurs instances d’un même démon en fonction de comment celui-ci est configuré.


Un démon est une DLL dont le nom se termine par « Daemon.dll », et qui doit être placée dans le même dossier que SystemHell.exe

Lorsque SystemHell démarre, il regarde dans son dossier s’il existe un fichier de configuration « Daemons.xml »

Si ce n’est pas le cas, SystemHell va rechercher dans son dossier toutes les DLL censées posséder un démon, et générer un « Daemons.xml » qui possédera la configuration pour une instance de chaque démon.

Comment développer un démon ?


Entrons tout de suite dans le vif du sujet. Pour ce faire, nous allons créer un démon simple puis le faire évoluer au fur et à mesure de nos besoins. Cela permettra de voir l’ensemble des possibilités offertes par SystemHell.

Allons-y :

Pour commencer, nous allons créer une nouvelle solution dans laquelle nous pourrons développer plusieurs démons. Nous l’appellerons « MyHellProject »

Création d'un solution vide MyHellProject

Nous allons créer dans cette solution un nouvelle DLL qui sera notre premier démon. Nous allons appeler cette DLL « HelloWorldDaemon »

Création d'une librairie HelloWorldDaemon.dll

Maintenant que nous avons une DLL, et que nous nous sommes bien assuré que le nom d’assembly se termine par le mot « Daemon », nous allons télécharger le package nuget « SystemHell » qui nous permettra de développer et de déployer notre démon.

Ouverture du gestionnaire de packages Nuget

Recherche du package SystemHell

Après avoir coché le projet « HellowWorldDaemon » et cliqué sur le bouton « Install », une référence à la librairie « SharedDaemonLib » s’ajoute à votre projet.

Ajout de la librairie SharedDaemonLib dans les références de la solution

A partir de là, nous allons pouvoir passer à la partie développement.

Pour commencer, nous allons créer une classe qui fera office de classe de configuration. Cette classe devra contenir tous les paramètres qui pourront être défini par l’administrateur pour faire tourner notre service.

Dans notre cas, nous allons mettre une phrase qui devra être écrite en boucle dans DbgView ainsi qu’un nombre de secondes qui définira la fréquence à laquelle afficher cette phrase.

public class HelloWorldConfiguration : DaemonModuleConfiguration
{
    private string _whatToSay = "Hello World !";
    private int _loopTimeInSecond = 5;

    public string WhatToSay
    {
     get { return _whatToSay; }
     set { _whatToSay = value; }
    }

    public int LoopTimeInSecond
    {
     get { return _loopTimeInSecond; }
     set { _loopTimeInSecond = value; }
    }
}

Comme vous pouvez le remarquer, notre classe doit hériter de la classe de base DaemonModuleConfiguration.

Une autre chose importante à savoir, c’est que toutes les propriétés de cette classe doivent être initialisées et accessibles en get / set. (Surtout pour les types string)

Si vous n’initialisez pas ces propriétés, elles risques de ne pas apparaître dans le fichier de configuration généré automatiquement par SystemHell. Il faudra donc que l’administrateur les connaissent par cœur pour les ajouter à la main.

Maintenant que nous disposons d’une classe de configuration, nous allons pouvoir créer le point d’entrée vers notre démon. Pour cela, nous allons ajouter une classe qui hérite de DaemonBase, et nous définirons en paramètre générique le type de notre classe de configuration défini plus haut.


public class HelloWorld : DaemonBase<HelloWorldConfiguration>
{
 public override void Start(CancellationToken cancellationToken)
 {
  throw new NotImplementedException();
 }
}

Quand SystemHell va démarrer, il va appeler le Start de cette classe dans un nouveau Thread en lui passant un CancelationToken.

Pour ceux qui ne sont pas très familier avec la TPL, ce token permet de savoir si l’appelant a demandé à ce que l’exécution du Thread soit interrompu, donc à savoir si l’administrateur à fait une demande « Stop » sur le service.

Il est donc de la responsabilité du développeur de devoir gérer le CancelationToken.

Il ne reste plus qu’a implémenter notre démon comme ceci :

public class HelloWorld : DaemonBase<HelloWorldConfiguration>
{
 public override void Start(CancellationToken cancellationToken)
 {
  DaemonStarted = true;
  do
  {
   WriteTrace("Daemon say : {0}", Configuration.WhatToSay);
  } while (!cancellationToken.WaitHandle.WaitOne(Configuration.LoopTimeInSecond*1000));
 }  
}

Quelques explications sur ce code s’imposent :

DaemonStarted est une valeur booleenne issue de la classe de base qui a pour rôle de notifier à SystemHell que le démon a démarré correctement.

Effectivement, comme la méthode Start à pour vocation à ne jamais rendre la main, SystemHell à besoin que vous définissiez cette valeur à "true" pour lui notifier que le démon à correctement démarré.

Nous arrivons ensuite dans une boucle do/while qui est conditionnée par l’attente d’un signal sur le CancelationToken. Si ce signal renvoi « true », la méthode Start sort de la boucle infinie et SystemHell termine l’exécution du démon.

Nous voyons aussi que ce code fait référence à une propriété de la classe de base appelée « Configuration ». Comme vous l’avez surement deviné, cette propriété correspond à la classe de configuration défini plus haut, à ceci prêt que SystemHell a injecté les données issues du fichier « Daemons.xml » qui est manipulable par un administrateur.

Pour mieux comprendre tous ces concepts, nous allons maintenant installer et configurer ce démon sur notre machine.

Installation et exécution de notre premier démon


Après avoir compilé « HelloWorldDaemon.dll », nous pouvons aller chercher le programme SystemHell.exe qui nous permettra de le hoster. Pour cela, faites un clique droit sur le projet, et choisissez le menu « Ouvrir le dossier dans l’explorateur »

Ouverture du dossier dans l'explorateur

Dossier ou se situe le projet HelloWorld

Remontez d’un dossier pour attendre « MyHellProject » puis allez dans le dossier « Package »

Navigation jusqu'au dossier Packages

Ce dossier contient tous les packages Nuget téléchargés pour notre solution. Allez dans le dossier « systemHell.x.y.z » puis dans le sous dossier « tools ». Vous trouverez un exécutable appelé « systemHell.exe »

Navigation jusqu'au dossier "Tools" qui contient SystemHell.exe

Copiez cet exécutable dans le dossier où vous désirez installer votre service système, et profitez-en pour y placer votre dll « HelloWorldDaemon.dll » compilée précédemment, ainsi que ses dépendances.

Copie de l'exécutable dans un dossier

Ouvrez maintenant un interpréteur de commande en mode « Administrateur », puis tapez la commande suivante pour installer le service sur votre ordinateur :

Installation du service "HelloWorld" avec "sc.exe"

Attention : il doit y avoir un espace entre binPath= et le chemin vers SystemHell.exe

Normalement, une fois cette commande exécutée, vous trouverez un service nommé « HelloWorld » dans votre SCM.

Présence du service "HelloWorld" dans la SCM

Très bien.

Démarrez le service « HelloWorld » grâce à la SCM. Normalement un message d’erreur indique que le service n’a pas pu démarrer.

Message d'erreur suite au démarrage du service "HelloWorld"

Pour comprendre un peu plus ce qu’il se passe, vous pouvez aller dans l’observateur événements

Erreur SystemHell dans l'observateur d'événements

L’erreur indique que le service s’est arrêté car il n’y avait pas de fichier de configuration. Un fichier a été généré dans « c:\temp\test\Daemons.xml », et il suffit d’aller le configurer puis de relancer le service.

Ouvrons ce fichier de configuration pour voir ce qu’il contient.

Fichier de configuration généré par SystemHell pour HelloWorld

Voici comment est structuré ce fichier :

Le nœud « Modules » contient un ou plusieurs nœuds « Daemon » qui représentent pour chacun une instance de démon à charger.

Un nœud « Daemon » possède les attributs suivants :

Name : représente le nom du démon, celui-ci doit être unique dans le fichier « Daemons.xml »

Actif : Défini si SystemHell doit exécuter ce démon. Attention, lorsque le fichier de configuration est auto généré, tous les démons ont l’attribut « Actif » à « false » par défaut. Pensez à le passer à « true » sans quoi vous constaterez que votre démon ne démarre pas.

Assembly : Défini le nom fort de l’assembly qui possède le code du démon. Cette assembly doit être située dans le même dossier que « SystemHell.exe ». Attention : Comme vous pouvez le constater, le nom fort de l’assembly possède le numéro de version. Si vous avez besoin d’attribuer des numéros version à votre démon, modifiez le numéro de version du fichier, et non celui de l’assembly, sinon 
SystemHell risque de ne pas pouvoir charger l’assembly de votre démon.


Modification du numéro de version de fichier plutôt que celui de l'assembly


Le sous nœud « Configuration » possède les propriétés que nous avons créées dans notre classe « HelloWorldConfiguration. ». Attention, si vous ajoutez de nouvelles propriétés dans votre classe, pensez bien à les répercuter à la main dans le fichier de configuration.

Maintenant que nous avons vu comment était constitué ce fichier, nous allons le manipuler pour bien comprendre comment celui-ci fonctionne.

Pour commencer, nous allons définir l’attribut « Actif » de notre démon à « true », pour notifier à SystemHell que ce démon doit être chargé.

Activation du démon HelloWorld dans le fichier de configuration

Maintenant procurez-vous l’exécutable DbgView disponible sur le site de Microsoft à l’adresse suivante : https://technet.microsoft.com/en-us/sysinternals/debugview.aspx

NB : si le lien de téléchargement est mort, faites une recherche de « dbgView » sur Google, vous le trouverez très facilement.

Une fois l’exécutable obtenu, lancez-le en mode « Administrateur » puis allez dans le menu « capture » et assurez-vous que l’option «Capture Global Win32 » est active.

Activation de l'option "Capture Global Win32" dans DebugView

Retournez dans la SCM, puis lancez le démarrage du service « HelloWorld »

SystemHell démarre notre démon dont l’activité est visible dans la console « DbgView »

Visualisation de l'activité du démon dans DebugView

Arrêtons notre démon pour faire un petit changement dans le fichier de configuration

Changements dans le fichier de configuration

Redémarrons le service « HelloWorld » pour voir ce qu’il se passe

Activité du démon "HelloWorld" après redémarrage

Comme vous pouvez le constater, il est extrêmement simple de configurer notre démon avec le fichier XML !

Maintenant, nous allons créer deux instances de notre démon pour que l'in répète en boucle "bonjour" toutes les 10 secondes  et l"autre "au revoir" toutes les 5 secondes.

Pour cela, il suffit de dupliquer le nœud « Daemon », et d’appliquer des configurations différentes. Attention à bien faire en sorte que l’attribut « name » soit unique dans le fichier de configuration.

Configuration pour activer deux instances du démon "HelloWorld"

Visualisation de l'activité des deux instances du démon "HelloWorld"

Et voilà, vous venez de créer votre premier démon. Celui-ci est paramétrable, configurable et administrable très facilement.

Allons un peu plus loin...


Les commandes personnalisées

Un service Windows à la possibilité de recevoir des commandes personnalisées via la commande « sc control », c’est-à-dire que nous pouvons demander à notre démon d’effectuer certaines actions à la demande de l’administrateur.

Pour implémenter cette fonctionnalité, rien de plus simple, il suffit de surcharger la méthode « OnCustomCommand » dans notre démon.

Par exemple, si nous reprenons le code de notre démon « HelloWorld », voici comment nous pourrions le modifier.


public class HelloWorld : DaemonBase<HelloWorldConfiguration>
 {
  public override void Start(CancellationToken cancellationToken)
  {
   DaemonStarted = true;
   do
   {
    WriteTrace("Daemon say : {0}", Configuration.WhatToSay);
   } while (!cancellationToken.WaitHandle.WaitOne(Configuration.LoopTimeInSecond*1000));
  }

  public override void OnCustomCommand(int command)
  {
   WriteTrace("la commande numéro {0} a été reçue.", command.ToString());
  }
 }

Comme vous pouvez le constater, une commande est un numéro passé en paramètre. Le MSDN précise que ce numéro doit être compris en 128 et 255, les numéros en dessous de 128 étant des valeurs réservées au système d’exploitation.

Envoyons une commande à notre service « HelloWorld » à l’aide de la commande « sc control », et observons ce qu’il se passe :

Envoi de la commande 150 au service HelloWorld

Réception de la commande 150 par SystemHell

Nous voyons dans DbgView à la ligne 6 que SystemHell a reçu la commande « 150 » que nous lui avons envoyée, et celui-ci l’a transféré à tous les démons qu’il héberge.

Activer ou désactiver des instances de démon sans redémarrer SystemHell

La commande personnalisé numéro « 200 » est une commande spéciale qui permet à SystemHell d’activer ou désactiver un démon sans avoir besoin de le redémarrer !

C’est-à-dire que nous allons pouvoir modifier notre fichier de configuration « Daemon.xml » pour ajouter de nouveaux nœuds ou jouer sur les attributs « Actif » de nos démons existant, puis appliquer nos modifications via la commande « sc control mon_service 200 »

Regardons comment ça se passe dans la pratique avec notre démon HelloWorld.

Nous allons partir du principe que le service HelloWorld héberge 2 démons. Notre but est de désactiver le démon « HelloWorld_2 » sans redémarrer le service.

Visualisation de l'activité des deux instances de démon

Ouvrons le fichier configuration, et passons l’attribut « Actif » de « HelloWorld_2 » à « false »

Modification du fichier de configuration pour désactiver HelloWorld_2

On envoi maintenant une commande 200 à notre Service HelloWorld pour que SystemHell puisse appliquer la modification.

Envoi de la commande 200 au service "HelloWorld"

Observons l’impact de cette commande dans « DbgView »

Visualisation de l'impacte dans dbgview

Nous voyons à la ligne 222 que SystemHell a procédé à un rechargement des démons. Après cette opération, seul le démon HelloWorld_1 est fonctionnel.

Notez que nous aurions atteint le même résultat si nous avions supprimé le nœud XML du démon « HelloWorld_2 » dans le fichier de configuration.

Nota Bene : La commande « 200 » permet à SystemHell d’activer ou désactiver des démons sans redémarrer le service. Cette commande ne permet pas de recharger une nouvelle configuration pour un démon en cours d’exécution.

Si votre service héberge plusieurs démons et que vous avez besoin de modifier la configuration de l’un d’eux sans avoir à redémarrer le service, passez l’attribut « Actif » à « false », changez les informations de configurations souhaitées, appelez la commande 200 pour arrêter le démon, repassez l’attribut « Actif » à « true » puis rappelez la commande 200 pour redémarrer le démon.

Les fichiers de configurations complexes

Il arrive parfois qu’il soit nécessaire de structurer notre configuration pour que celle-ci soit plus facilement manipulable, ou qu’elle représente beaucoup de données. 

Dans ce cas, il devient nécessaire d’ajouter des classes et des sous-classes à notre classe de configuration.

Ceci est bien sûr possible avec SystemHell : pour cela rien de plus simple, il suffit d’ajouter des classes à votre classe de configuration qui contiennent l’attribut « Serializable »

Exemple :

public class HelloWorldConfiguration : DaemonModuleConfiguration
    {
     public HelloWorldConfiguration()
     {
      SubData = new Subclass1();
     }
     private string _whatToSay = "Hello World !";
     private int _loopTimeInSecond = 5;

     public string WhatToSay
     {
      get { return _whatToSay; }
      set { _whatToSay = value; }
     }

     public int LoopTimeInSecond
     {
      get { return _loopTimeInSecond; }
      set { _loopTimeInSecond = value; }
     }

  public Subclass1 SubData { get; set; }     
    }

 [Serializable]
 public class Subclass1
 {
  public Subclass1()
  {
   MyData = new Subclass2();   
  }
  private string _property1 = "this is property 1";
  private int _property2 = 1;

  public string Property1
  {
   get { return _property1; }
   set { _property1 = value; }
  }

  public int Property2
  {
   get { return _property2; }
   set { _property2 = value; }
  }

  public Subclass2 MyData { get; set; }
 }

 [Serializable]
 public class Subclass2
 {
  private string _myPoperty = "this is my property";

  public string MyPoperty
  {
   get { return _myPoperty; }
   set { _myPoperty = value; }
  }
 }


Voici ce que cela donne lorsque le fichier de configuration est généré par SystemHell :

Fichier de configuration complexe

Notez que les nœuds XML du fichier de configuration correspondent aux noms des propriétés, et non au nom des classes.

Pour que SystemHell puisse générer le XML correspondant à vos sous-objets, faites bien attention à ce que vos propriétés soient déclarées en « public », et que les objets soient bien initialisés dans le constructeur.

BadImageFormatException, ou comment passer SystemHell en x86

SystemHell.exe est un exécutable compilé en « Any CPU », c’est-à-dire que si celui-ci est lancé sur un système d’exploitation en 64 bits, il s’exécutera en 64 bits, sinon il s’exécutera en 32 bits (x86 pour les intimes)

Parfois, il arrive que nous mettions au point un démon qui utilise une dépendance compilée en x86, ce qui nous force à configurer la compilation de notre DLL en conséquence.

Définition de la plateforme cible du démon en x86

Dans ce cas, il est fort probable que SystemHell ne puisse pas démarrer à cause de l’erreur « BadImageFormatException »

Pour régler ce problème, nous allons devoir appliquer une astuce pour forcer SystemHell.exe à s’exécuter en 32 bits à l’aide de l’outil « corflags.exe ».

Cet exécutable se trouve en plusieurs exemplaires dans « programfilesx86\microsoft SDKs »

Recherche de l'outil CorFlags.exe sur le disque dur

Si vous ne le possédez pas sur votre machine, une simple recherche sur internet vous permettra de vous le procurer.

Une fois que vous avez mis la main sur cet exécutable, utilisez le pour vérifier les propriétés de SystemHell.exe

Consultation des flags CLR de SystemHell avec CorFlags.exe

Nous voyons ici que SystemHell n’est pas en 32 bits, heureusement nous pouvons l’y forcer en utilisant la commande « CorFlags.exe /32BIT+ SystemHell.exe »

Forcage du flag 32 bits sur SystemHell

Une fois la commande exécutée, nous pouvons voir que le flags « 32 bits » a bien été appliqué.

Consultation des flags CLR de SystemHell avec CorFlags.exe

Voilà, vous pouvez maintenant lancer SystemHell pour que celui-ci exécute votre démon 32 bits sans problème.

Exemples de produits


Voici quelques projets professionnels basés sur SystemHell pour vous montrer ce qu'il est possible de faire.

Astread

Page d'accueil de astread.com

http://www.astread.com est un service en ligne gratuit qui permet de convertir un livre électronique en livre audio. Celui-ci compte à l’heure actuelle plus de 500 utilisateurs qui ont déjà généré environ 5000 heures d’écoute.

La génération de livre audio est basée sur un démon SystemHell qui reçoit un ordre depuis le site.

Une fois la demande gérée, le démon post une réponse après avoir créé et déposé le livre audio dans un endroit approprié à son téléchargement.

Visualisation de l'activité SystemHell de www.astread.com

Le démon embarque un service WCF pour communiquer avec le site web, et différent paramètres permettent de lui indiquer où générer les documents audio, et comment gérer la parallélisassions du travail en fonction de la machine hôte.

Fichier de configuration SystemHell de astread

Avec SystemHell, Astread est capable de gérer sa monté en charge grâce à la mise en place rapide de nouveaux démons sur des machines virtuelles.

Le système tourne depuis 6 mois non-stop, et a souffert récemment d’un problème qui a été rapidement identifié.

Effectivement, un dead lock dans la librairie « DotNetZip » faisait planter la génération de certains fichiers audio. L’architecture du démon a permis de corriger et déployer très rapidement une nouvelle version en production.

Connecteur HL7

HL7 est une norme de communication dans le monde de la santé qui permet de transmettre des informations entre plusieurs systèmes logiciels au sein de cabinets, de cliniques ou d’hôpitaux.

Pour ce faire, l’éditeur qui désire pouvoir être compatible HL7 doit créer un connecteur capable de générer des messages au format texte en fonction d’événements qui se produisent dans le système d’information (admission d’un patient, création du compte rendu, facturation, …)

Une clinique ou un hôpital peuvent recevoir plusieurs centaines de patients par jour, et chaque patient génère une dizaine d’événements qui doivent être envoyés en HL7 à des tiers, il est donc primordial que le connecteur qui tourne en fond de tâche soit extrêmement robuste pour ne pas perturber le worflow de prise en charge.

Or, HL7 est une norme très complexe qui a bénéficié de nombreuses évolutions. Le connecteur doit donc pouvoir gérer plusieurs versions de la norme et s’assurer à chaque évolution qu’aucune régression n’a été introduite dans le code.

Grace à SystemHell, nous avons pu écrire en quelques semaines un connecteur HL7 capable de gérer plusieurs profils dans 2 versions de la norme. La grande souplesse du framework a permis de mettre en place des tests unitaires ainsi que des scénarios en « Behavior Driven Development » pour valider automatiquement le bon fonctionnement du connecteur à chaque modification de code.

Le déploiement et la configuration du connecteur ont ainsi été grandement simplifiés, ce qui a permis aux installateurs de s’approprier l’outil très rapidement, et de pouvoir mettre en place plusieurs types de stratégies en fonction du contexte d’installation (création de services séparés, création d’un seul service, ciblage de plusieurs types d’appareil, suivit et diagnostique des anomalies, …)

Exemple de scénarios BDD du connecteur HL7

Exemple de fichier de configuration du démon HL7

Ce démon est actif dans plusieurs cabinets de radiologie et a permis d’acheminer plusieurs millions de messages sans jamais défaillir.


Système de dictée numérique

Des utilisateurs qui font de la dictée numérique désiraient que leurs fichiers son puissent être placés automatiquement dans une GED (Gestion Electronique de Document), un répertoire, un partage réseau ou un serveur FTP.

De plus, le fichier son pouvait provenir soit d’un dossier faisant office de puit de fichiers, soit depuis un appareil spécifique qui agissait comme une clé USB.

La multitude de configurations et le mode fond de tâche devant tourner 24/24 étaient tout indiqués pour créer un démon SystemHell dont voici le fichier de configuration :

Fichier de configuration du démon de dictée numérique

Comme vous pouvez le constater, SystemHell permet de créer des fichiers de configuration très complexes, selon la stratégie choisie par le développeur.

Dans notre cas, le système possède deux concepts : des « watchers » permettent de configurer comment surveiller une entrée de fichier son (mode répertoire ou USB) et des « Behaviors » permettent de spécifier comment le démon doit se comporter lorsque un fichier a été détecté par le « watcher » (envoi dans une GED, un répertoire ou du FTP).

Ainsi, le démon peut être installé soit sur un serveur, soit directement sur un poste utilisateur en fonction du besoin final.

BubbleBugs

Page d'accueil du site www.bubblebugs.net

BubbleBugs est un site permettant de faire remonter les erreurs qui se produisent dans des applications « .NET » directement dans un serveur TFS ou VSO sous forme de WorkItem (http://www.bubblebugs.net)

Pour ce faire, l’utilisateur doit s’inscrire sur le site et donner les informations de connexion vers son dépôt de fichiers source, puis intégrer une librairie à son application.

Lorsque un utilisateur a validé les informations de connexion à son dépôt, un nouveau nœud XML est créé dans le fichier de configuration SystemHell, et une commande 200 est envoyée pour démarrer un démon spécifique qui a la charge de surveiller un dossier, et créer un workitem correspondant chaque fois qu’un nouveau fichier apparaît dans celui-ci.

En parallèle, un autre démon qui tourne dans le même service à la responsabilité de recevoir les erreurs issues des applications en ligne, et de déposer dans l’un des dossiers correspondant le fichier qui contient tous les détails de l’erreur.

Ce site exploite toutes les possibilités offertes par SystemHell : il combine deux démons différents qui travaillent de concert, et permet de créer une nouvelle instance à la volé pour chaque inscription sur le site, sans redémarrer le service.

Fichier de configuration SystemHell du site bubblebugs

Visualiation de l'activité du démon BubbleBugs

Conclusion


Les services Windows sont des applications spécifiques dont la robustesse et la maintenabilité ne sont pas négociables, il est donc nécessaire de mettre toutes les chances de son côté lorsque vous devez en développer un.

En utilisant SystemHell, vous serez en capacité de créer rapidement des services Windows facilement testables et configurables tout en assurant la scalabilité de votre architecture.

SystemHell est un Framework Open Source accessible sur Github à l’adresse https://github.com/aboudoux/systemHell

Si vous avez besoin de conseils pour votre architecture de services Windows, laissez donc un commentaire ! Je serai ravi d’en discuter avec vous.


Aucun commentaire:

Enregistrer un commentaire