Article - JRES 2015

Transcription

Article - JRES 2015
Modernisation des échanges de données
individus dans le SI
Arnaud Grausem
Responsable des développements logiciels – Université de Strasbourg
Université de Strasbourg – Direction Informatique
Alain Zamboni
Architecte du Système d'Information
Université de Strasbourg – Direction Informatique
Résumé
La gestion de l'accès et des échanges de données au sein de systèmes d'information de plus en plus
complexes est aujourd'hui une préoccupation importante pour l'ensemble des établissements
universitaires. En effet, leur taille augmente, du fait de fusions d'établissements ou même de
rapprochement avec des établissements d'enseignement régionaux. Plusieurs produits ont vu ou verront
le jour en terme de référentiel comme GRHUM [1] ou bientôt SINAPS [2].
Par ailleurs, les échanges de données se modernisent et les tendances s'éloignent progressivement des
opérations de synchronisation base à base à fort couplage pour converger vers des bus de données [3]
permettant la connexion aisée d'applicatifs au moyen de configurations plutôt que de développements
spécifiques. Des notions de services web, de middleware d'échanges et de transformations de messages et
de tables de routage pour les données apparaissent progressivement dans nos SI respectifs.
Nous verrons comment l'Université de Strasbourg a commencé à converger vers des solutions de ce type
en misant sur :
•
une forte couche d'abstraction pour définir les objets métiers, afin de rendre plus aisée la
compréhension des données récupérées, et ce quelle que soit sa source ;
•
la notion d'Acmeism [4], en propulsant des spécifications telles que SPORE [5] afin
d'harmoniser les échanges dans un environnement technique fortement hétérogène ;
•
la construction en interne d'un référentiel définissant la nouvelle source de données des
individus de notre SI.
Après une expérience de production de plus de deux ans, nous verrons quelles sont les pistes d'évolutions
permettant de fluidifier davantage les échanges, de la production à l'exploitation de l'ensemble de nos
données.
Mots-clefs
Bus de données, Référentiel, WebService, SPoRE, Message queue, Données individus, Websockets
1 De la mise en place d'un référentiel au sein du SI
1.1
Contexte et besoins
Le projet Alisée, débuté en 2011 et abandonné à l'horizon 2014, prévoyait la mise en place du nouveau SI
Scolarité, fondé sur la solution Banner [6]. Au début du projet, il est devenu rapidement nécessaire de
posséder un élément central contenant un ensemble de données de référence pour le SI. Le projet avait
JRES 2015 – Montpellier
1/13
alors besoin des données relatives aux personnels de l'Université de Strasbourg et de l'École Nationale du
Génie de l'Eau et de l'Environnement de Strasbourg (ENGEES). Il imposait de propager les changements
survenus très rapidement, pour ne pas dire instantanément. De plus, une contrainte liée à la duplication
potentielle des individus provenant d'Harpège, d'Apogée et du SI de l'ENGEES devait être gérée en
détectant et fusionnant les duplications avant tout envoi.
Après plusieurs tentatives de mise en place de l'application InfoSphere Master Data Management de
l'éditeur IBM, seul le composant nous permettant de détecter et de fusionner les potentiels doublons a été
jugé satisfaisant. L'outil de modélisation du schéma de référentiel fut abandonné. L'alimentation sera donc
double : à la fois vers l'outil de « dédoublonnage », appelé par la suite MDM, et le futur référentiel.
1.2
1.2.1
Modèle de données
Périmètre
Nous avons ainsi modélisé nous-mêmes le schéma du référentiel et avons décidé de n'y intégrer que les
données caractérisant les individus qui sont disponibles à la fois dans Harpège et Apogée. Ainsi, nous
avons modélisé l'état civil, les statuts de personnel, d'étudiant et d'externe, les adresses ainsi que les
fonctions des individus. À ceci s'ajoute bien entendu un identifiant unique permettant de faire le lien avec
l'enregistrement contenu dans la source de données.
1.2.2
Alimentation
Suite à des soucis calendaires, nous sommes partis sur une alimentation sous forme de synchronisation
entre les sources de données et le référentiel. Les sources de données s'ajoutant, nous nous sommes très
rapidement rendu compte que cette solution n'était pas pérenne à terme et nous causerait des problèmes de
lenteur. Il était donc impossible de faire chuter la cadence des opérations.
À titre d'informations, dans les sources de données supplémentaires, nous comptons des informations
provenant de Graal, Ldap ainsi que de notre outil de personnalisation de l'adresse physique sur le campus.
1.2.3
« Dédoublonnage », entité et « golden record »
Une fois les données synchronisées dans les deux backends, MDM et référentiel, une opération visant à
rapprocher les enregistrements est effectuée. Chaque rapprochement d'enregistrement est ensuite déversé
dans notre référentiel pour créer une entité, qui est, par définition, la somme des membres rapprochés qui
le composent.
Au sein du référentiel, pour chaque nouvelle entité, sera créé un objet « GoldenRecord ». Un
« GoldenRecord » représente un individu à part entière pour lequel un calcul des valeurs des attributs
communs aux membres a été effectué. Ce calcul est guidé par des règles créées par nos soins.
1.3
Architecture finale, limites et perspectives
La conception du référentiel, dont la première version a vu le jour début 2014, a été fortement influencée
par les besoins du projet Alisée. Les délais contraints nous ont empêchés de travailler plus avant sur une
alimentation en temps réel du référentiel, cassant en quelque sorte notre volonté de proposer une donnée
fraîche à la demande. Au sein même du référentiel, la mise en place d'une détection de la génération d'un
« golden record » pour envoi instantané vers Alisée (via un moteur Banner BEIS [7]) laissait entrevoir de
belles pistes pour l'avenir.
Parallèlement, le périmètre même des données à intégrer au sein du référentiel fait encore débat. Faut-il
en mettre plus ? Faut-il se contenter d'y intégrer les identifiants permettant de remonter vers les
enregistrements de la base source ? Ce sont des questions que nous continuons à nous poser, au cas par
cas. De plus, la question du moteur à utiliser pour stocker ces données revient très souvent. Le moteur
JRES 2015 – Montpellier
2/13
SQL est-il pertinent ? Doit-on se diriger vers des moteurs NoSQL ? Si oui, lesquels ? Nous expérimentons
aujourd'hui les deux mondes et convergeons au final vers les nouvelles possibilités offertes par le SGBD
PostgreSQL.
Figure 1 - Architecture finale du référentiel conçue en janvier 2014
JRES 2015 – Montpellier
3/13
2 Les échanges de données individus
2.1
Abstraction et formalisation
Le nommage des attributs des objets métier manipulés est très souvent directement dépendant de la source
de données du système d'information dans laquelle ces attributs sont définis. La compréhension de ces
données est très souvent rendue difficile par le manque de cohérence de ces nommages. Certains objets
métier, ainsi que l'état dans lequel ils se trouvent au sein d'une source de données, nécessitent autant une
connaissance approfondie du métier correspondant qu'une compétence technique relative à la source de
données. Pourtant, dans la plupart des cas, leur formalisation concrète est simple. L'accès aux données et
leur compréhension doit donc être simplifié pour une autonomie accrue des intégrateurs et développeurs
d'applications.
2.1.1
Vocabulaire
Le premier travail d'abstraction des données individus a constitué en l'établissement d'un vocabulaire
commun pour tous les objets métiers manipulés et les valeurs les caractérisant :
―
―
pour chacun des attributs se retrouvant dans plusieurs sources de données, nous avons déterminé
un nom unique en créant de fait un mapping avec leur nom réel au sein de chaque source de
données ;
un effort de nommage a été entrepris pour tous les autres champs, qu'ils soient directement issus
d'une source, ou résultant d'un calcul entre plusieurs champs.
À titre d'exemple, nous trouvons le champ représentant un « prénom » dans toutes les bases sources de
notre SI :
•
givenName (LDAP) → first_name
•
LIB_PR1_IND (Apogee) → first_name
•
etc...
2.1.2
Objets métiers et états
Dans un second temps, savoir comment récupérer des données relatives à une population fine se révèle
être complexe dès lors que l'on ne possède que peu de connaissances sur les bases de données métier. En
effet, bien que nous pouvons aisément énoncer ce qu'est par exemple un étudiant diplômé, il est difficile
d'avoir accès directement à cette population. Nous avons ainsi défini un certain nombre de populations en
les rendant directement accessibles, sans que la connaissance de leur représentation dans une source de
données soit requise.
2.2
2.2.1
Points d'accès aux données
Limiter le nombre de points de cassure
Les travaux énoncés dans le paragraphe précédent ont pour but de rationaliser l'accès aux sources de
données. En effet, un grand nombre d'applicatifs utilisent des connexions directes et maintiennent donc
localement un client. Les conséquences et les coûts de maintenance sont bien trop importants dès lors que
le parc applicatif croit et les sources de données évoluent. Nous avons donc opté pour une mise à
disposition des données sous forme de services web pour chaque source de données importante du
système d'information. L'exposition des données ne change pas pour les clients même si le service web
doit évoluer en fonction des évolutions des différents backends. Cette centralisation permet également
une meilleure cohérence dans l'utilisation des données de chacune des sources. Le seul point de cassure
JRES 2015 – Montpellier
4/13
devient le service web lui-même, mais si cassure il y a, elle peut avoir bien plus de conséquences.
2.2.2
Utilisation de standards du monde web
Pour exposer ces données, nous utilisons des standards éprouvés dans le domaine web :
―
le protocole HTTP au moyen d'une architecture REST ;
―
le format JSON pour la représentation des données ;
―
l'authentification par token pour chaque application.
2.2.3
Contrôle des accès et autorisations
Nous avons mis en place un dispositif fin de droits d'accès aux données pour chacun de nos services web,
et ce selon trois angles différents :
―
―
―
2.3
des droits primaires de lecture, écriture, modification et suppression peuvent être définis par objets
métier exposés pour chaque application ;
nous pouvons agir sur des ensembles de données exposées pour une application par la définition
de filtres. Ainsi, nous pouvons décider par exemple de réduire les données exposées aux étudiants
inscrits pour l'année en cours sur le service web d'accès aux données scolarité ;
nous pouvons agir également sur les attributs de chaque objet métier pour une application donnée.
Nous pouvons ainsi choisir de n'exposer que les attributs nécessaires aux besoins d'une application
et ne pas permettre une action sur l'ensemble des attributs d'un objet métier exposé.
Favoriser l'accès aux API
Permettre l'accès à des services web demande également un effort côté client. Par ailleurs, le risque de
retomber dans les travers d'un client développé pour chaque application est grand, avec la problématique
du maintien en fonction des évolutions. Dans le cas de clients mis à disposition et maintenus, il y a
également le risque de devoir développer et maintenir des clients pour bon nombre de langages de
programmation. Nous avons misé sur l'Acmeism, courant de pensée préférant transformer les bonnes
idées en spécifications pouvant être implémentées dans la majorité des langages de programmation.
2.3.1
Utilisation de SPoRE
SPoRE (Specification of a Portable Rest Environment) est une spécification visant à décrire de façon
simple les services web de type REST et permettre, au moyen de cette description, de générer des clients
de haut niveau durant l’exécution même. La spécification SPoRE a déjà été implémentée dans de
nombreux langages, comme Perl, Python, Ruby, PHP, Java ou encore Groovy. L'Université de Strasbourg
a intégré rapidement cette communauté et est devenue, au fil des années, moteur dans le maintien et
l'évolution de cette spécification, initialement créée par une start-up parisienne du nom de Linkfluence.
Nous maintenons également les implémentations Python et Groovy, très largement utilisées au sein de
notre SI.
Chacun de nos services web est décrit intégralement par une spécification servie au niveau de chaque
service web déployé. Voici un extrait de la description du service web LDAP pour la création et la
récupération de comptes temporaires :
JRES 2015 – Montpellier
5/13
{
}
"name": "LDAPUDS API",
"authority": "Unistra:DI",
"base_url": "https://ldap-ws.u-strasbg.fr",
"formats": ["json" ],
"version": "0.1",
"methods": {
"create_temporary": {
"path": "/people/temporaries.:format",
"required_params": [ "format" ],
"method": "POST",
"authentication": true,
"required_payload": true,
"documentation": "Create list of temporary account"
},
"get_temporary": {
"path": "/people/temporaries/:username.:format",
"required_params": [ "format", "username" ],
"method": "GET",
"authentication": true,
"documentation": "Get a temporary account details"
}
}
Voici un exemple d'utilisation de cette description au sein du client SPORE Python, nommé britney [8] :
import britney
import json
client = britney.new('http://path-to-spec.fr',
base_url='https://ldap-ws.univ.fr')
response = client.get_temporary(username='tmp1', format='json')
temporary = json.loads(reponse.text)
2.3.2
Écriture de middlewares spécifiques
Les clients s’occupent uniquement de la création des requêtes à transmettre et de la gestion des réponses
transmises par le serveur. En résumé, toute la couche HTTP est gérée entièrement par le client car c'est le
point commun entre l'ensemble des services web de type REST. Pour tout ce qui dépend plus fortement
du service web attaqué, comme l'authentification ou la gestion des formats, la spécification décrit un
fonctionnement par middlewares pouvant agir sur la requête avant sa génération et sur la réponse avant sa
restitution finale au client. Certains middlewares fréquemment utilisés sont inclus dans les librairies dans
les langages cités plus haut. Par exemple, pour gérer une authentification de type Basic, on pourra activer
le middleware adéquat :
JRES 2015 – Montpellier
6/13
import britney
from britney.middleware import auth
client = britney.new('http://path-to-spec.fr',
base_url='http://ldap-ws.univ.fr')
client.enable(auth.Basic, username='toto', password='tata')
Créer ses propres middlewares est relativement aisé et permet de spécialiser son client pour les besoins
spécifiques d'accès à un service web donné.
2.4
Envoi de données
Rapidement, il est devenu nécessaire de posséder une brique logicielle permettant de diffuser des données
au sein du système d'information. Au-delà d'un simple service web de propagation d'informations, son
implémentation le définit plus comme un moteur de worklow qu'un bus de données. En fonction de la
route appelée par un client, l'application permet de diffuser des informations vers de multiples sources,
gérées par des plug-ins. Ces derniers sont découverts à l'exécution en fonction de la route appelée et des
droits de l'application cliente. Les plug-ins peuvent appeler indifféremment des scripts distants, des
services web ou réaliser des opérations directement dans une source de données. Pour palier à des
problèmes survenant sur une des destinations, un système de spool a été mis en place pour rejouer à
intervalles réguliers les données en erreur.
Par exemple, cet outil, appelé Merlin au sein de notre SI, est utilisé dans le processus de création des
comptes temporaires. Il se chargera d'appeler correctement les services web LDAP, et des AD qui se
chargeront de créer proprement les comptes.
Figure 2 - Processus de création de comptes temporaires
JRES 2015 – Montpellier
7/13
2.5
Agrégation et accès aux données
Capitalisant sur la réussite des processus gérés par Merlin, cité précédemment, nous avons décidé de
reprendre la libraire nous permettant de découvrir à l'exécution les plug-ins appelés selon les droits d'un
client et la route appelée, pour créer le service web de consultation des données du référentiel. En effet,
comme nous le disions plus haut, nous avons fait le choix de mettre dans notre référentiel les seules
données utiles à définir un individu, et communes à l'ensemble des sources de données. Cependant, les
besoins se sont faits pressants quant à la récupération de données plus spécifiques contenues dans les
sources elle-mêmes.
2.5.1 De l'emballement…
Le moteur a ainsi permis de chercher les données propres à une source, après avoir préalablement
récupéré les éléments contenus dans le référentiel, en appelant les services web correspondants. Les
données issues du référentiel permettent de faire le lien avec les enregistrements distants. L'ensemble des
données, une fois récupérées sont agrégées et restituées au client.
L'ensemble du projet d’intégration de notre nouveau Système Intégré de Gestion de Bibliothèque a été
réalisé avec cet outil, nommé Camelot, et a permis notamment de réaliser de l’agrégation depuis les
services web LDAP, Apogée mais également depuis des services web d'accès aux SI de différents
établissements partenaires comme l'INSA de Strasbourg, la BNU de Strasbourg ou l'ENGEES.
JRES 2015 – Montpellier
8/13
Figure 3 - Recherche d'un membre étudiant par le SIGB via Camelot
2.5.2 … à l'abandon potentiel
Ce système étant prévu à la base pour réaliser des actions à la demande, il n'est ni dimensionné, ni prévu
pour réaliser des batchs de synchronisation. Or, au final, le projet SIGB l'a utilisé sous cette forme.
De plus, la complexité d'implémentation de ce moteur d’agrégation induit de fortes difficultés
d'exploitation. Les demandes nous parvenant étant souvent très spécifiques, notre difficulté à le faire
évoluer sans régression a rapidement été mis en lumière.
2.6
Limites et perspectives
Le moteur nous permettant de gérer la propagation de données dans le SI est une vraie réussite. Il nous a
permis de gérer de multiples processus, comme la création de comptes temporaires, le changement de mot
de passe ou encore la mise en place de la politique d'expiration des comptes utilisateur. Capitaliser sur
cette réussite nous a desservi sur plusieurs points quant à l'exposition des données de référence :
―
―
―
nous n'avons pas une chaîne complète nous permettant d'exposer des données à la demande. La
mise à jour du référentiel et surtout des données dédoublonnées est trop longue pour des
applicatifs ayant besoin de données fraîches. Ceci a notamment empêché l'utilisation du référentiel
lors de l'intégration du nouveau Système de Gestion de cartes ;
l'exposition des données à la demande ne répond pas aux besoins d'intégration de façon
systématique. Certains applicatifs ont besoin d'un ensemble de données à jour en continu et pas
seulement au moment où la donnée peut être récupérée ;
la gestion des droits relatifs aux applicatifs sur l'outil Camelot est beaucoup trop complexe à
exploiter et toute modification de l'outil peut entraîner de fortes régressions.
Nous devons, dans un premier temps, permettre un rafraîchissement quasi-instantané de notre référentiel
pour les intégrations d'applicatifs ayant besoin de données fraîches. Dans un second temps, il faut revoir
les modèles d'exposition des données pour qu'ils correspondent à l'ensemble des besoins. Si aujourd'hui,
les applicatifs développés en interne s'intègrent bien au dispositif, il n'en est rien des applicatifs externes.
3 Bus de données événementiel
Le projet sur lequel nous travaillons est la réalisation d'un bus de données événementiel permettant de
propager des messages, eux-mêmes routés par un nœud central. Utilisé dans un premier temps pour palier
aux problèmes d'alimentation actuel de notre référentiel, il pourra très certainement être étendu par la
suite. Voici un schéma représentant la solution vers laquelle nous nous tournons.
JRES 2015 – Montpellier
9/13
Figure 4 - Architecture du futur bus de données événementiel
3.1
Alimentation du référentiel
3.1.1
Capter les changements
La problématique essentielle provient des changements dans les bases maîtres que sont Harpège, Apogée
et Graal. Comment capter les changements qui nous intéressent pour les répercuter instantanément dans
notre référentiel. C'est une problématique sur laquelle se penche le projet SINAPS, qui est très
certainement confronté aux problématiques qui sont les nôtres aujourd'hui. Plusieurs pistes sont
disponibles :
―
―
―
l'utilisation du moteur Oracle Streams [9] permettant de diffuser des changements sur des tables et
colonnes configurées au préalable. Cet outil sera déprécié dans les futures versions d'Oracle.
l'utilisation du nouveau moteur Oracle GoldenGate [10] ayant les mêmes caractéristiques que
l'outil précédent, et compatible avec les futures version d'Oracle. Cet outil est très onéreux ;
l'écriture de triggers directement en base de données, impliquant un effort important d'exploitation
et de maintien.
Les nouvelles versions d'Oracle arriveront rapidement. Bien qu'ayant obtenu des résultats probants sur
nos travaux avec Oracle Streams [9], nous ne pouvons nous permettre de continuer à capitaliser sur cet
outil. L'achat de la solution Golden Gate [10] est quant à elle impossible. Nous ne pouvons que nous
remettre à travailler sur une solution basée sur des triggers.
La finalité du travail est par contre la même. Le résultat de nos travaux consiste en la mise à jour d'une
JRES 2015 – Montpellier
10/13
table de mouvement.
3.1.2 Diffuser les événements
La table de mouvement créée, nous avons mis en place un système d'écoute qui nous permet de diffuser
des événements typés en rapport avec les objets métiers correspondants. Ainsi nous pourrons transmettre
des événements de création, de modification ou de suppression pour chaque élément surveillé par les
triggers.
3.2
Vers un bus de données global
3.2.1
Capitaliser sur les standards utilisés
Les technologies mises en place pour l'exposition des données ont été un point positif depuis le début de
la construction du moteur d'échanges de données au sein du SI. Pour mettre en place ce bus d'échanges
nous avons décidé de reprendre cette approche en favorisant :
―
―
―
3.2.2
JSON comme format des échanges, qui pourra évoluer vers MessagePack, toujours dans des
soucis d'Acmeism ;
les websockets pour créer des canaux de communication full-duplex entre les différentes briques ;
l'utilisation d'un protocole d'envoi de messages utilisant les technologies citées plus haut et
disposant d'une spécification Acmeique [4].
WAMP & Crossbar.io
Nous avons été rapidement convaincus par le protocole WAMP [11], en nous fondant sur les critères
suivants :
―
Support du « Publish & Subscribe» (PubSub) ;
―
Support d'appels de procédures distantes (RPC) ;
―
Support d'appels de procédures distantes routés (Routed RPC) ;
―
Utilisation native dans un environnement Web ;
―
―
« Acmeique » [4] dans le sens où la spécification est implémentable dans les langages de
programmation majeurs ;
Caractère Open-Source de la spécification, qui trouve déjà plusieurs implémentations dans des
technologies différentes.
Par ailleurs, la thèse Web Technologies for the Internet of Things [12], comparant plusieurs technologies
permettant de définir facilement des flux de données, nous a permis de rapidement converger vers cette
spécification. De plus, cette dernière adoptée, il a fallu choisir une implémentation pour tester les
possibilités offertes. Nous nous sommes rapidement tournés vers l'implémentation des créateurs de la
spécification, qui, en plus d'être l'implémentation la plus mature, utilise Python, langage faisant partie du
socle technique de la Direction Informatique de l'Université.
Crossbar.io permet de router des messages entre composants et est une implémentation open source de la
spécification WAMP [11]. Le couplage des composants est faible et permet leur communication en temps
réel. Les possibilités offertes et implémentées dans Crossbar.io [13] sont de deux types :
―
―
RPCs : appels de procédures distantes. Crossbar renvoie le résultat au composant ayant fait l'appel.
Au préalable la procédure doit être déclarée auprès de Crossbar.io [13] par le composant
l'exposant ;
PubSub : publication d’événements et abonnements à certains événements.
JRES 2015 – Montpellier
11/13
Le moteur scrutant les insertions sur la table des mouvements publiera un événement au moyen d'un
client WAMP [11], à chaque nouveauté. De son côté, le client côté référentiel écoutera les événements
propagés dans une file dédiée.
Figure 5 - Schéma global de propagation des changements vers le référentiel
Au-delà de la simple diffusion des changements vers le référentiel, le moteur Crossbar.io [13] offre des
possibilités intéressantes et peut permettre l'implémentation de processus métier relativement complexes
de manière simple. Dans une optique de développement d'applications web, l'utilisation de websockets
permet notamment de diffuser des messages jusque dans un navigateur.
3.2.3 Roadmap
Ayant testé le fonctionnement de diffusion des changements repérés dans Harpège et LDAP vers notre
référentiel, nous souhaitons, au-delà de la mise en place d'un routeur crossbar :
―
―
―
―
Utiliser le moteur NoSQL de PostgreSQL au niveau du référentiel dès lors que cela est pertinent ;
Choisir un processus métier tel que par exemple l'envoi des modifications opérées sur les
personnels enseignant dans Harpège vers Apogée en temps réel, et l'implémenter avec le nouveau
système en place ;
Proposer de nouveaux modes d'intégration d'applicatifs au moyen de technique PubSub ou RPC.
Trouver des applicatifs ayant des besoins forts en termes de rafraîchissement de données provenant
du système d'information directement au niveau du navigateur web.
JRES 2015 – Montpellier
12/13
Bibliographie
[1] Consortium cocktail - page du projet GRHUM http://www.cocktail.org/cgibin/WebObjects/Webgenie.woa/wa/default?type=32260&wgtg=_blank
[2] AMUE – page du projet SINAPS http://www.amue.fr/pilotage/logiciels/sinaps/
[3] Wikipedia – Article sur les bus de données https://fr.wikipedia.org/wiki/Enterprise_service_bus
[4] Définition de l'Acmeism http://acmeism.org/home/
[5] Spécification SPORE http://github.com/SPORE/specifications/blob/master/spore_description.pod
[6] La solution Banner éditée par Ellucian http://www.ellucian.com/student-information-system/.
[7] Moteur d'intégration Banner au sein d'un système d'information universitaire
https://ellucianlive.activeevents.com/2014/connect/sessionDetail.ww?SESSION_ID=1993
[8] Client SPORE Python https://github.com/agrausem/britney
[9] Oracle - Page du projet streams
http://docs.oracle.com/cd/B28359_01/server.111/b28321/strms_over.htm
[10] Oracle – Page du projet Golden Gate http://www.oracle.com/us/products/middleware/dataintegration/goldengate/overview/index.html
[11] Spécification WAMP : Web Application Messaging Protocol http://wamp-proto.org/
[12] Fuguo Huang - Web Technologies for the Internet of Things
https://into.aalto.fi/download/attachments/12324178/Huang_Fuguo_thesis_2.pdf, 2013
[13] Une implémenation de WAMP – Crossbar.io http://crossbar.io/
JRES 2015 – Montpellier
13/13