Instructions: Gestion des états pour les services
Ces instructions portent sur l'utilisation de services avec état et de services sans état et sur leur effet sur les performances et la robustesse. Elles portent également sur l'approche transactionnelle nécessaire pour l'interaction. La notion de gestion des états dans un environnement SOA peut être divisée en trois catégories principales : l'état de transaction, l'état de sécurité et l'état fonctionnel.
Relations
Eléments connexes
Description principale

Introduction

La notion de composants avec ou sans état est très importante pour le développement d'applications réparties et de systèmes, même si elle n'a intégré le vocabulaire courant que récemment. Cette notion signifie que si deux composants ou deux services sont en train de communiquer et qu'un état est géré pour la durée de la conversation avec le client, il est possible qu'un incident survienne dans le composant serveur (ou qu'il y ait une défaillance du réseau) signifiant que le client ne peut pas terminer la conversation et doit recommencer. Cette notion implique également que le réacheminement des requêtes client vers un des ensembles de composants est effectué, à moins que l'ensemble des composants partage le même magasin de données pour l'état de la conversation. Ce problème est très courant dans le développement d'applications Web et l'état de l'application est soigneusement géré de façon à l'éviter autant que possible. L'état de l'application est géré par le client, par la conversation elle-même (en passant l'état dans chaque message) ou par des composants avec état côté serveur conçus de manière précise. L'exemple le plus courant pour les interactions Web avec état est le panier. Les utilisateurs s'attendent à ce que leur panier soit conservé s'ils quittent leur poste quelques instants, mais comment cela est-il possible avec 100 000 utilisateurs connectés simultanément ?

Cependant, cela ne signifie pas que les composants avec état sont préjudiciables par nature ; ils sont simplement une source potentielle d'incidents au niveau des performances et de la résilience, à moins d'être gérés et développés à l'aide de standards plus rigoureux. En fait, toutes les applications de gestion contiennent des services dont la nature est de gérer ou de représenter les entités avec état ou qui contiennent des services auxquels il faut accéder dans un certain ordre. En fait, l'architecture J2EE définit une bean session avec état et une bean session sans état pour souligner ces questions de manière explicite ; elle définit également certaines restrictions pour les composants avec état. Cela donne une classification simple des services avec état, notamment des raisons faisant qu'on ne peut pas les éviter. Il peut être obligatoire pour un service d'avoir un état pour l'une des raisons suivantes :

Le service conserve l'état du client : c'est l'exemple du panier. Pour une raison ou pour une autre, des données doivent être conservées sur des appels entre le client et le service. Ces données font partie de la conversation et, si on n'y prête pas attention, peuvent donc associer le client à des ressources serveur spécifiques.

Le service gère une ressource avec état : dans ce cas, le service gère souvent un ensemble de ressources ou d'entités, chacune d'entre elles ayant un état. Par exemple, une commande client a un état, un commutateur réseau a un état, etc. L'interface d'un service qui gère l'objet en fermant ou en différant une commande, ou encore en redémarrant un commutateur, change donc l'état d'une entité en particulier.

Le service a un protocole avec état : dans ce cas, le service effectue les opérations qu'il fournit dans un ordre logique. Il comporte, par exemple, les opération login (), dostuff () et logoff () ; ce dont on peut déduire qu'il n'est pas possible d'appeler les opérations dostuff () et logoff () si l'opération login () n'a pas été appelée.

Une autre forme d'état très courante dans les architectures de composants, mais qui n'est pas applicable dans le monde des services, est la notion d'état transactionnel. Dans le contexte des composants, il est possible d'établir qu'une méthode get () et update () sur un composant soit appelée par un client dans le cadre d'une transaction créée et maintenue par le client. La méthode update() doit changer un stockage transactionnel sous-jacent. Cela implique l'intervention de la plateforme middleware pour coordonner les transactions et s'assurer que les méthodes nécessitant des transactions soient appelées par un client ayant une transaction ouverte. Pour les services, il n'est pas conseillé de suivre un modèle dans lequel les transactions, au sens classique de validation en deux phases, restent ouvertes pour plusieurs appels de services. Des standards sont en cours de développement pour les transactions des différents appels de services, mais ils suivent un paradigme fondamentalement différent (une compensation) et sont pris en charge différemment par les plateformes middleware.

La technique la plus évidente pour le développement efficace des services avec état, que nous avons déjà évoquée, consiste à externaliser l'état du service, rendant ainsi explicite le fait que ce service a un état, mais aussi que cet état peut être identifié comme faisant partie de la spécification de service. Cette question est abordée ci-après pour les deux classes de services avec état.

Comme la plupart des services logiciels seront développés à partir d'une plateforme middleware existante, comme J2EE ou Microsoft.NET, ces architectures de plateforme comportent des techniques d"implémentation pour faciliter la gestion de l'état. Ces instructions portent donc principalement sur des techniques de conception pour certaines classes de services avec état. Il convient aussi de remarquer qu'il ne s'agit pas d'une préoccupation nouvelle. Dans le cadre du développement de grands systèmes, les développeurs, les concepteurs et les architectes ont rencontré et décrit depuis des années le développement de transactions interactives et non interactives à l'aide d'IBM Customer Information Control System avec des clients écran vert (actuellement 3270 terminaux).

Etat de conversation persistant

Il vaut mieux éviter cette situation. Quand cela est possible, si une conception fait appel à la gestion d'état lors de la conversation entre un service et ses clients, il vaut mieux décider de choisir une autre approche. Si cela n'est pas possible, externalisez cet état en faisant passer toutes les données d'état nécessaires entre le service et le client avec chaque message indiquant l'intégralité de la conversation. Cette approche peut signifier que la taille des messages a beaucoup augmenté, mais le service lui-même est à présent totalement sans état. Une autre approche consiste à placer un identificateur de conversation dans chaque message et à conserver l'intégralité de la conversation dans un magasin de stockage de données, comme une base de données. Si cela entraîne des conséquences importantes sur les performances du serveur, elles peuvent être contrebalancées par les performances du réseau et du client entraînées par des messages plus petits.

Ces services sans état ont pour objectif premier de fournir un ensemble de services identiques pouvant gérer n'importe quelle requête en utilisant des techniques d'équilibrage de charge pour distribuer les clients. Cet équilibrage de charge est possible si tout l'état est externalisé et conservé dans le même magasin de stockage de données.

Gestion des ressources avec état

Dans ce cas, il faut considérer la gestion des ressources qui ont un état explicite. En fait, cet état est un aspect important de la ressource elle-même. Il est possible que l'on puisse décrire l'état de la ressource, la commande du client ou le commutateur réseau décrits ci-dessus en utilisant une machine d'état, en décrivant les états valides, mais aussi la façon dont les opérations fournies par le service affectent l'état des ressources sous-jacentes.

Lors de cette description, il faut remarquer que cet état fait partie intégrante des ressources. Toutefois, cela n'est pas forcément exprimé de manière explicite dans le modèle d'informations qui la représente. Il faut aussi souligner que lorsque l'on gère un ensemble d'entités, il faut être capable d'identifier les ressources individuelles que l'on affecte, qu'elles aient ou non un identificateur explicite.

Lorsqu'un service représente l'accès à une entité physique ou la requête de l'état d'une entité physique, comme un commutateur réseau ou un élément de contrôle de processus, il n'est pas possible d'externaliser l'état de l'entité. L'analyse d'une valve est le seul moyen de connaître son état. Même s'il est possible de construire et de répondre à l'aide d'un message décrivant l'état actuel de la valve, cela n'est pas une situation permanente. L'état de la valve peut changer au cours de la transmission ou du traitement de ce message.

Dans le domaine des services Web, il existe un ensemble de nouveaux standards, le WSRF (Web Services Resource Framework) qui porte sur les patterns des services avec état et sur les approches pour coder l'état, principalement pour les services représentant la gestion de ressources avec état. Pour plus d'informations, consultez le site IBM WS-ResourceFramework.

Spécifications sur les services avec état

L'exemple mentionné ci-dessus implique un service ayant une organisation logique des opérations qu'il fournit. De nombreux services fourniront des interfaces de cette forme. Cela est parfois lié aux ressources d'état, mais alors l'ordre des opérations dépend de l'état de la ressource gérée. Dans ce cas, l'ordre dépend de la conversation elle-même. L'exemple suivant illustre la spécification d'un service ayant un protocole associé, en commençant par la spécification structurelle, puis une machine d'état indiquant la spécification du comportement est décrite.

Diagramme décrit dans le contenu textuel.

La commande peut avoir l'un des états suivants {Ouverte, Annulée, Réalisée, Fermée) et change en fonction des opérations fournies par la spécification ci-dessus. Dans le cas d'une autotransition de l'état ouvert, l'opération ChangementCommande est réalisée par l'envoi de la notification de ce changement.

Diagramme décrit dans le contenu textuel.

Lorsque les services sont développés au sein d'une entreprise unique et avec une portée technique, des spécifications de comportement détaillées peuvent être développées ou décrites de manière moins formelle, sous forme de texte. Lorsque les services sont exposés en dehors de ce type de portée, par exemple entre des partitions, ils représentent une spécification logique des interactions entre les partitions et doivent être développés plus en détails. Les spécifications détaillées permettent aussi une réutilisation plus efficace par les utilisateurs lorsque les services sont censés être réutilisés souvent.