CICS vu d'avion

le 23/11/2009 par Thomas Vial
Tags: Software Engineering

Cet article a pour but de vous présenter CICS de manière très macroscopique. Baignant moi-même dans le monde dit « distribué » (par opposition à celui du mainframe, le host), je trouve intéressant de faire l’exercice d’y voir autre chose qu’une boîte noire mythique, dont la seule description fait appel à un jargon ésotérique...

L’exercice n’est pas pour autant inutile, puisque nos missions chez OCTO impliquent souvent de s’intégrer avec de tels systèmes. Vous allez voir d’ailleurs que les parallèles avec le distribué sont plus nombreux qu’on pourrait le croire !

Introduction

CICS, ou Customer Information Control System, a une longue histoire. Il apparaît à la fin des années 60, alors que le tout nouveau système S/360 d’IBM apporte aux utilisateurs les joies du téléscripteur : l’interactivité en « temps réel » avec le système, par opposition aux traitements de masse, est pour ainsi dire à portée de main. Dans ce contexte, qui devient tout de suite concurrentiel, IBM se doit d’apporter sa solution de traitement en ligne ; ce sera CICS, en 1968. Le produit était au départ destiné aux services publics, alors mal armés pour assurer un service client de proximité dans des agences dispersées, mais la flexibilité avec laquelle il avait été conçu lui ont fait conquérir tout de suite d'autres secteurs. Bizarrement, IBM sort à la même époque un système fonctionnellement très proche, IMS (Information Management System) pour les besoins du programme Apollo (!).

Pour en revenir à CICS, il se présente tout de suite sous la forme d’un système de gestion de transactions et d’un ensemble d’APIs pour des langages variés : assembleur, COBOL, PL/1, … Tout cela a bien évolué mais reste le cœur, connu sous le nom de CICS Transaction Server, d’une ligne de produits bien fournie. Encore maintenant, on trouve CICS (tout comme IMS) majoritairement sur mainframe, notamment sur les plateformes z/OS. Il continue d’évoluer en s’ouvrant de plus en plus sur l’extérieur (le monde distribué), tout en restant très bien implanté grâce à ses performances et à sa robustesse. Et aussi parce que beaucoup d’organisations (banque, assurance, distribution, institutions, …) maintiennent des applicatifs sur gros et moyen système !

Un avertissement avant de rentrer dans le vif : je ne suis pas du tout un spécialiste CICS. Le matériel de base de cet article provient d’observations faites au gré de missions, et de la documentation en ligne de CICS sur les sites d’IBM. Cette documentation, dont le lien est donné en fin d’article, est très complète et assez accessible, bien que touffue. N’hésitez pas à approfondir… Enfin, si vous constatez des erreurs dans cet article, n’hésitez surtout pas à les signaler par le biais des commentaires du blog : tout le monde en profitera, moi le premier :).

NB : des termes de « jargon » et des noms de fonctionnalités apparaissent souvent ; ils sont en italique.

Vue d’ensemble

On pourrait représenter une configuration CICS typique de la manière suivante :

CICS vu d'avion

Vu ainsi, plus qu’un transaction server, c’est un véritable application server. Je suppose que CICS AS n’aura pas été retenu comme nom commercial :) (à l’anglo-saxonne CICS se prononce kicks).

Nous allons maintenant décrire chaque élément de ce schéma.

Régions CICS (les bulles)

Sur un même système, peuvent cohabiter plusieurs instances de CICS que l’on appelle régions (ou partitions). Même si elles peuvent communiquer entre elles (voir plus loin), elles sont indépendantes, aussi bien vis-à-vis des ressources qu’elles gèrent que de leur cycle d’arrêt/relance.

Dans les organisations, on rencontre souvent une région CICS par environnement (développement, recette, production, …).

Ressources

A l’intérieur d’une bulle se trouve tout ce que CICS va gérer pour nous. Pour CICS, tout est ressource (on entend parfois l'expression « un OS dans l’OS »). Chaque ressource fait obligatoirement partie d’un groupe, que l’on peut comparer à une unité de déploiement. Pour l’exemple, les groupes sont représentés sous formes d’applications. La suite de l’article détaille ces ressources par type.

Transactions et maps

C’est le nerf de la guerre... Vue de l’extérieur une transaction est un point d’entrée d’une application qui déclenche l’exécution d’un programme ; pour CICS c’est une unité de traitement (UOW, Unit Of Work) qui respecte les propriétés ACID (Atomicité – Cohérence – Isolation – Durabilité) que l’on sous-entend habituellement en parlant de transaction.

Transactions interactives

Les transactions d’interaction avec un utilisateur (= un terminal, via le protocole 3270 et ses variantes) sont comme des contrôleurs dans le paradigme MVC. Elles peuvent soit gérer entièrement les interactions avec le terminal (mode conversationnel), soit reposer sur le mécanisme de maps de CICS (mode pseudo-conversationnel).

Le mode conversationnel est à éviter autant que possible car les ressources que la transaction manipule sont implicitement verrouillées par CICS, même pendant que la transaction attend que l’utilisateur ait fini sa saisie… Une règle d’or stipule justement que les transactions doivent rester les plus courtes possibles pour assurer des temps de réponse acceptables quelle que soit la charge.

Dans le mode pseudo-conversationnel (celui représenté sur le schéma avec « Tran IHM 1 » et « Tran IHM 2 »), chaque transaction fait partie d’une cinématique. Elle reçoit en entrée le contenu de l’écran (map) précédent et envoie le masque de son propre écran avant de chainer vers la transaction suivante ; CICS s’occupe de l’interaction avec le terminal et d’appeler les transactions unitaires. Celles-ci durent alors juste le temps de leur traitement individuel et ne verrouillent que ponctuellement les autres ressources. L’inconvénient est que pendant les phases d’interaction, les ressources sont ouvertes à des accès concurrents : à l’application de mettre en place les mécanismes d’intégrité adéquats, comme du verrouillage optimiste par exemple.

Transactions non interactives

Quant aux transactions non interactives, elles servent typiquement d’émissaires vis-à-vis d’autres applications ou même de l’extérieur distribué, via les connecteurs décrits plus loin. Une pratique courante est la mise en place de « transactions chapeaux », qui sont des points d’entrée uniques vers les services métier des applications CICS. Elles se chargent de vérifier les paramètres d’entrée, éventuellement les habilitations de l’appelant, et de router vers la bonne transaction métier (qu’elles peuvent déterminer à la volée, ou recevoir en paramètre technique).

Autre cas d'usage : certains middlewares comme la CTG (voir plus bas) se connectent au CICS par le biais d'un compte technique unique, afin de gérer efficacement des pools de connexion. Une transaction chapeau est l'endroit idéal pour recevoir l'ID utilisateur réel en paramètre, et appeler des transactions métier existantes sous son identité plutôt que sous celle du compte technique.

Les transactions non interactives sont enfin utilisées pour réagir à des événements extérieurs, comme par exemple l’arrivée de nouveaux enregistrements dans un fichier surveillé par CICS – le fichier est alors vu comme une file de messages. Ce mode de déclenchement événementiel s'appelle ATI (Automatic Transaction Initiation).

Programmes

Ils contiennent la logique de l'application ; ce sont des programmes compilés comme les autres… ou presque ! Ils doivent être déployés comme ressources tout comme les transactions qui les appellent. En général ce sont des bibliothèques de programmes métier, dont les transactions orchestrent les appels pour effectuer un traitement. Un programme peut aussi être appelé directement, appeler des sous-programmes, qui eux-mêmes, … La seule contrainte est d’utiliser les APIs CICS pour coder ces appels, afin que le système garde la main sur le flot des appels, et puisse maintenir les structures de mémoire partagées, qui font l’objet de la section suivante.

Les structures de mémoire

Tout d’abord, chaque programme, transaction ou non, a sa mémoire privée, comme n’importe quel programme.

Mais en plus de cela, CICS offre des mécanismes de partage de mémoire à plusieurs niveaux :

  • pour la durée d’exécution d’une transaction (Transaction Work Area aka TWA, et User Storage) : ces mémoires sont accessibles par tous les programmes participant à la transaction

  • au sein d’une paire de programmes appelant/appelé (COMMAREA structurée et channels) : ces structures permettent de passer des données en entrée et d’en renvoyer en retour

  • entre plusieurs transactions opérant sur un même terminal (Terminal Control Table User Area aka TCTUA) : cette mémoire permet d’implémenter un espace de stockage de type « session » lors d’une pseudo-conversation

  • entre toutes les transactions (Common Work Area aka CWA, Temporary Storage aka TS, et datasets (fichiers)) : à charge des transactions d’utiliser cette mémoire à bon escient !

Dans chaque catégorie, les différentes options se distinguent par les mécanismes d’allocation (en amont, ou bien à la demande) et d’accessibilité (directe par mapping d’espace d’adressage, ou indirecte par recopie et marshaling). Le choix dépend donc des cas d’utilisation – transaction locale, distribuée, etc. – et de considérations de performance, en fonction des besoins en mémoire estimés lors de la phase de conception.

Les ressources managées : fichiers, pools de connexion DB2

Les programmes peuvent bien sûr accéder à des fichiers quelconques du système, ou à d’autres objets extérieurs à CICS. Cependant, déclarer de tels objets comme ressources CICS permet de bénéficier des fonctions de récupération et de verrouillage par rapport aux accès concurrentiels, ce qu’on recherche en général en environnement transactionnel qui respecte ACID.

Ainsi, avec des ressources de type fichier (datasets) déclarés comme recoverable, une transaction va pouvoir accumuler des modifications et verrouiller des enregistrements jusqu’à ce qu’elle requière un commit partiel (syncpoint) – explicitement ou bien implicitement quand elle se termine. A l’inverse elle peut émettre un ordre de rollback ou se terminer en erreur, ce qui conduit à l’annulation (backout) des modifications en cours. Plusieurs niveaux de « récupérabilité » sont par ailleurs possibles, selon la manière dont on veut protéger chaque fichier contre les crashes du système. Les fichiers managés, qu’ils soient recoverable ou non, servent également à mettre en œuvre les files de messages pour le mécanisme ATI décrit plus haut.

Noter que sur mainframe, ce contrôle fin des accès aux données (jusqu'au niveau enregistrement) repose fortement sur les fonctionnalités natives qu’offre l’OS avec les fichiers VSAM.

Pour les bases de données, CICS s’intègre à DB2 par le biais de pools de connexions, qui sont simplement des ressources d’un type particulier, et par la déclaration des transactions susceptibles d’y accéder. CICS ne fait que s’appuyer sur les transactions natives de DB2 pour assurer la même qualité de service qu’avec les fichiers.

Connecteurs

Ce sont eux qui vont permettre d’ouvrir le CICS, aussi bien dans le sens entrant que sortant, à d’autres programmes.

Il y a tout d’abord des connecteurs de CICS à CICS – d’autres régions sur le même hôte, ou bien des instances distantes. Ils permettent d’accéder à des ressources du partenaire, comme des fichiers ou des espaces de mémoire partagés (function shipping), ainsi que d’appeler des transactions distantes aussi bien en synchrone qu’en asynchrone (Distributed Program Link aka DPL, et Distributed Transaction Processing aka DTP). Un nombre arbitraire de systèmes peut ainsi participer à une grosse transaction distribuée, sécurisée par le protocole de commit à deux phases – noter toutefois que si les APIs offrent des facilités pour mettre ce protocole en œuvre, c’est aux transactions de le faire en pratique !

A un niveau d’ouverture différent, l’interface EXCI (EXternal CICS Interface) offre une API d’appel au CICS depuis l’environnement MVS de l’hôte – depuis des programmes non CICS donc. Un cas d’usage intéressant est la réutilisation de transactions dans des batches.

Enfin on trouve des connecteurs réseaux et notamment TCP/IP. Ces derniers sont des ressources comme les autres et offrent des accès au CICS selon plusieurs protocoles : IIOP voire EJB, ECI, HTTP (simple, SOAP ou REST), … Concrètement, ce sont des listeners, associés à des programmes capables de router vers la transaction ou le programme que l’on souhaite appeler (par exemple en fonction de l’URL, dans le cas du connecteur HTTP).

Tant qu’on est dans l’intégration, citons deux grands middlewares de connectivité, qui vont venir se brancher sur ces connecteurs : Microsoft Host Integration Server (anciennement SNA Server), et CICS Transaction Gateway (la fameuse CTG, très utilisée dans le monde Java).

Sécurité

CICS sait protéger, par le biais de RACF (le principal composant de sécurité du mainframe), l’accès à des ressources, que ce soient des composants centraux de CICS ou tout type de ressource managée que les transactions vont manipuler – y compris les transactions elles-mêmes bien sûr.

Conclusion

En prenant la peine de se pencher dessus, sans beaucoup rentrer dans les détails, on constate que le fonctionnement de CICS n’est pas si éloigné de ce qu’on connaît en distribué, et on y retrouve peu ou prou les mêmes patterns : APIs, services émissaires, séparation métier/présentation, … Je vous laisse deviner qui est le précurseur. L’article de Sylvain, Monsieur Jourdain et la SOA, va d'ailleurs dans le même sens.

Voilà qui devrait rendre les applications CICS moins mystérieuses… Et pour encore plus de confiance, exigez du code développé avec CobolUnit !

CESF GOODNIGHT

Sources et liens utiles

  • L’étagère de docs sur CICS 3.2, et particulièrement l’ouvrage Application Programming Guide

  • Le CICS wiki, beaucoup de contenu destiné aux personnes qui l'utilisent au jour le jour, mais on y trouve aussi des infos générales intéressantes

  • Wikipedia a bien sûr une page sur CICS