• Aucun résultat trouvé

Dans ce chapitre, nous avons étudié comment la réflexivité pouvait être utilisée pour la mise en œuvre de la tolérance aux fautes dans les systèmes logiciels complexes en dépit des limitations que nous avions identifiées à la fin du chapitre 3, page 50. Dans une première étape nous nous sommes intéressés à l’organisation multi-niveaux des systèmes complexes, pour mieux maîtriser la complémentarité entre les niveaux d’abstraction, que nous avions constatée au chapitre précédent, page 51. Cette discussion nous a amenés à souligner l’importance des liens inter-niveaux pour la compréhension de l’organisation d’un système logiciel complexe. Dans une seconde étape, nous avons cherché à mieux cerner les besoins opératoires de la tolérance aux fautes en introduisant la notion d’empreinte réflexive. Cette nouvelle notion nous a permis de discuter de façon générale des choix d’implémentation possibles lors de la réalisation de mécanismes de tolérance aux fautes dans une architecture multi-niveaux.

Les notions et les enseignements tirés de cette étude nous ont finalement permis de proposer une démarche en quatre étapes pour le développement d’architectures réflexives multi-niveaux dédiées à la tolérance aux fautes des systèmes complexes. C’est cette dé- marche que nous proposons maintenant d’illustrer sur un exemple concret (GNU/LINUXet CORBA), dans le chapitre suivant, qui termine notre mémoire.

Application à la réplication

N

OUSillustrons dans ce chapitre la démarche de développement d’une méta-interface multi-niveaux pour la tolérance aux fautes que nous avons proposée à la fin du chapitre précédent. Nous commençons par les aspects les plus génériques de cette approche, en illustrant la notion d’empreinte réflexive pour une famille bien connue de mécanismes de réplication (étape 1 de notre démarche).

Nous étudions ensuite comment les problèmes de contrôle du non-déterminisme et de capture d’état soulevés par l’empreinte obtenue peuvent être abordés sur une architecture CORBA/POSIX à brins d’exécution multiples (multithreaded) en utilisant la notion de lien inter-niveaux du chapitre précédent (étapes 2 et 3 de notre démarche).

Pour finir, nous validons notre approche par la réalisation d’un prototype de méta- interface sur une plate-forme à caractère industriel (GNU/LINUXet ORBACUS), ce qui nous

permet d’aborder la problématique de l’extraction d’un méta-modèle à partir des sources d’un composant, pour laquelle nous proposons une démarche générique (étape 4 de notre démarche).

5.1

Empreinte réflexive de la réplication

Nous nous intéressons dans cette section à la famille de mécanismes de réplication pré- sentés dans le projet DELTA-4 [Powell 1991], dont nous construisons l’empreinte réflexive, conformément à l’étape 1 de la démarche proposée au chapitre précédent. Le projet DELTA- 4 décrit trois stratégies de réplication d’une application client/serveur communiquant par messages : la réplication active, la réplication passive et la réplication semi-active. Ces trois approches ont en commun de tirer profit de la redondance acquise lorsqu’une même applica- tion est répliquée dans un système réparti pour masquer ses défaillances à l’utilisateur. Leurs

différences tiennent aux hypothèses faites sur le comportement de chacune des répliques, à la nature des fautes tolérées, à leurs difficultés respectives d’implémentation, et enfin aux sur–coûts induits en traitement et en communication.

5.1.1

Présentation des mécanismes étudiés

En réplication active, les différentes répliques ont des rôles symétriques, et traitent toutes les requêtes simultanément. Ce mode de réplication nécessite d’une part que les mêmes messages d’entrée soient fournis dans le même ordre à toutes les répliques (cohérence des entrées) ; et d’autre part que, partant du même état initial, les répliques produisent les mêmes messages de sortie, aussi dans le même ordre (déterminisme des répliques). Lorsque ces hypothèses sont respectées, la réplication active autorise un recouvrement très rapide des défaillances, puisque chacune des répliques peut à tout moment assumer seule le service répliqué. La réplication active permet aussi de tolérer les fautes en valeur d’une minorité de répliques par la mise en place d’un système de comparaison et de vote sur les réponses produites. On s’assure ainsi qu’une réponse valide sera toujours retournée à l’utilisateur. Le prix à payer pour ces différentes propriétés reste néanmoins une forte utilisation des ressources matérielles, tous les traitements devant être répliqués en permanence.

La réplication passive élimine ce fort sur-coût de traitement en introduisant une dissymé- trie dans le rôle des répliques. Une seule réplique, la réplique primaire ou primary, traite les requêtes en entrée et produit des sorties. Les autres répliques, les répliques de secours ou ba- ckups, sont maintenues synchronisées avec la réplique primaire par un transfert périodique de captures d’état (checkpointing). Le choix des instants de capture est déterminant pour assurer un masquage des défaillances complet à l’utilisateur. Il s’agit en fait du même pro- blème que celui à la base des protocoles de capture (checkpointing protocols), que nous avons présentés à la page 65 : les informations d’état transmises par la réplique primaire doivent permettre en cas de défaillance un basculement transparent du service sur les répliques secondaires. Dit autrement, les répliques secondaires doivent pouvoir assurer, à partir des captures d’état, une reprise qui soit cohérente avec le comportement perçu jusqu’alors par les clients du service répliqué (voir la section 3.1.1 page 37 sur le même sujet). En plus de ses avantages en termes de sur-coût de traitement en mode sans défaillances, la réplication passive, au contraire de la réplication active, ne requiert pas le déterminisme de l’application à laquelle elle s’applique. Cependant, les transferts de capture peuvent nécessiter des coûts de communication élevés, et les temps de recouvrement en cas de défaillance de la réplique primaire sont souvent plus longs, du fait de traitements qui n’étaient pas compris dans la dernière capture d’état et qui doivent être ré–effectués. Enfin, la réplication passive ne permet pas de tolérer les fautes en valeur, une seule réplique produisant des réponses.

La troisième forme de réplication, la réplication semi-active, a pour objectif de lever la contrainte du déterminisme qui vaut pour la réplication active. Elle ajoute des méca- nismes de « transfert », inspirés de la réplication passive, au mécanisme classique de la réplication active pour assurer un consensus entre les différentes répliques vis-à-vis de leurs décisions non-déterministes. Une réplique est choisie comme « meneuse » et est responsable

Stratégie Fautes tolérées Déterminisme Sur-coût

Traitement Communication Recouvrement

active fautes incontrôlées requis important faible faible

passive silence sur défaillance non–requis faible important important

semi-active fautes incontrôlées non–requis important faible faible

TAB. 5.1 :Propriétés et hypothèse des stratégies de réplication considérées

des décisions non-déterministes de l’application (ordonnancement des brins d’exécution, des messages, événements asynchrones) qui sont alors communiquées sous forme de noti- fications aux autres répliques, « suiveuses ». La réplication semi-active combine la plupart des avantages des deux autres formes de réplication : ses sur-coûts de communication et de recouvrement sont faibles, comme dans la réplication active, elle ne requiert pas le déterminisme, comme la réplication passive. De plus, en supposant un protocole de diffusion fiable entre meneur et suiveurs d’une part, et en supposant que les suiveurs soient capables de rejeter les choix invalides du meneur d’autre part, alors la réplication semi-active supporte aussi les fautes en valeur. Nous renvoyons aux sections 6.7 et 7.6 de [Powell 1991] pour une discussion plus détaillée de cette dernière propriété. Les différentes propriétés et les hypothèses sur lesquelles s’appuie chacune des stratégies sont reprises sous une forme résumée dans la table 5.1.

Les trois formes de réplication ainsi présentées nécessitent la mise en place de méca- nismes de détection d’erreur et de configuration, notamment pour relancer une réplique, ou mettre à jour la vision qu’ont du système les différentes répliques (protocole de groupe). Nous nous concentrons dans la suite de ce chapitre sur le problème de la capture d’état et de la maîtrise du non-déterminisme, et n’aborderons donc pas plus en détail ces aspects, qui restent essentiels cependant.

5.1.2

Empreinte réflexive

Nous présentons dans cette section une vision synthétique des empreintes réflexives des trois mécanismes de réplication que nous venons de présenter, conformément à l’étape 1 de notre démarche. En se basant sur les descriptions que nous venons d’en donner, les tables 5.2 à 5.4 page 79 présentent les différentes capacités réflexives nécessaires à la réalisation des mécanismes étudiés dans une architecture réflexive. Cette description s’appuie sur un modèle d’exécution abstrait, qui ne prend pour l’instant pas encore en compte la nature multi-niveaux de l’architecture sur laquelle nous souhaitons les implémenter. Les capacités décrites sont organisées en trois facettes, selon qu’elles ont trait à la communication entre les répliques et leurs clients, au contrôle de l’exécution des répliques ou aux données qu’elles traitent. La facette « données » tient plus à la structure d’un composant (quels attributs, quelles structures), alors que les facettes du « contrôle » et de la « communication » ont plus trait à son comportement.

Pour chacune de ces facettes, nous distinguons les entités du modèle d’exécution pour lesquelles des capacités réflexives doivent être fournies, ainsi que les aspects comporte-

mentaux de ces entités qui doivent être rendus accessibles. Nous n’avons pas distingué ici les différents types de capacités, réification, introspection, intercession, les trois formes intervenant sur chacune des entités considérées. On notera, comme nous l’annoncions dans la section 4.2.1 page 61, que les empreintes des stratégies individuelles se recouvrent largement, d’où le grand intérêt à considérer l’ensemble des capacités ainsi exposées dans le cadre d’une empreinte globale qui les réunisse toutes.