Ce huitième et dernier article sur JMX clôture cette petite série de posts sur JMX (cf. introduction, partie 1 portant sur les généralités, partie 2 portant sur les différents MBeans et le concept de Notification, partie 3 sur les agents JMX, partie 4 sur les classes de base, partie 5 sur le MBeanServer, partie 6 sur le chargement dynamique des MBeans et partie 7 sur les services JMX). Il abordera succinctement la notion de connecteur.
Table des matières
- JMX, qu’est ce que c’est?
- Spécifications
Les connecteurs
La spécification JMX défnit la notion de connecteurs : un connecteur est attaché à l’API JMX d’un MBean Server et le rend accessible de clients Java distants, le connecteur client possèdant une interface similaire à celle du MBean Server.
Un connecteur est donc constitué d’une partie cliente et d’une partie serveur :
- Le connecteur serveur est attaché au MBean Server et écoute les requêtes de connexion des clients
- Le connecteur client a pour rôle de trouver le server et d’étable une connexion avec ce dernier. Un connecteur client se trouve généralement dans une JVM différente du connecteur serveur et s’exécutera même généralement sur une machine différente.
Il est à noter que contrairement à un connecteur serveur, le connecteur client ne pourra se connecter qu’à un et un seul connecteur serveur (mais une application cliente pourra posséder plusieurs connecteurs clients).
JMX permet d’avoir de multiples connecteurs qui peuvent s’appuyer sur différents protocoles de communication entre le client et le serveur. Cependant, il définit le protocole standard et obligatoire sur tous serveurs JMX s’appuyant sur RMI (Remote Method Invocation) et le protocole optionel s’appuyant sur des sockets TCP et appelé JMXMP (JMX Messaging Protocol).
Les connecteurs distinguent deux notions distinctes qui sont la session et la connexion. Un connecteur client voit une session qui peut, tout au long de son cycle de vie de la session, avoir plusieurs connexions successives à un connecteur serveur. Il est à noter que, dans certains cas, il est possible d’avoir une connexion par requête (comme cela peut être le cas avec le protocole UDP ou JMS).
Une session possède un état sur le client mais pas nécessairement sur le connecteur serveur. Un connecteur, ne possède, quant à lui, pas forcément d’état.
Pour se connecter au connecteur serveur, le connecteur client peut utiliser une adresse du type service:jmx:jmxmp://host1:9876
. Si la requête de connexion aboutie, le point d’accès client du connecteur client est retourné en réponse.
Du point de vue de la connexion cliente, le code de l’utilisateur peut obtenir un objet qui implémente l’interface MBeanServerConnection
. Cette interface étant similaire à l’interface MBeanServer
, il devient transparent pour le code de l’application cliente d’interagir avec un MBean Server ne se trouvant pas dans la même JVM.
En fait, l’interface MBeanServerConnection
est étendue par l’interface MBeanServer
et contient donc toutes les méthodes principales sauf celles qui n’ont de sens que pour une utilisation locale.
Toutes les implémentations des connecteurs coté serveur doivent posséder un buffer de notifications qui correspond à la liste de toutes notifications émises par les MBeans à destination du MBean Server. Il est à noter que les connecteurs doivent supporter les requêtes concurrentes pour des raisons évidentes. Concernant l’adresse du serveur connecteur, il est conseillé, pour la générer, de passer par la classe JMXServiceURL
.
Afin de créer la partie cliente d’un connecteur, il existe deux possibilités :
- si l’adresse du serveur est connue, la méthode
connect(JMXServiceURL)
de la classe statiqueJMXConnectorFactory
peut être utilisée, - sinon, il est possible d’interroger le serveur pour obtenir un stub de
JMXConnector
.
Du point de vue de la connexion serveur, la connexion serveur est représentée par une sous-classe de JMXConnectorServer
qui peut être obtenue :
- soit à l’aide de la classe statique JMXConnectorServerFactory en lui indiquant le paramètre de type JMXServiceURL qui lui permet de connaitre les classes à instancier,
- soit en instanciant directement la sous-classe de JMXConnectorServer.
Le connecteur serveur doit être attaché à un MBean Server (ce qui ne signifie pas qu’il doit s’enregistré en son sein) et doit être actif pour être utilisable. Il peut être attaché auprès du MBean Server de deux manières :
- Le MBean Server auquel est attaché le connecteur serveur lui est spécifié lors de sa construction
- Le connecteur serveur est enregistré auprès du MBean Server comme s’il s’agissait d’un MBean
Exemple de création et d’attachement d’un connecteur serveur auprès d’un MBean Server
MBeanServer mbs = MBeanServerFactory.createMBeanServer();
JMXServiceURL addr = new JMXServiceURL("jmxmp", null, 0);
JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(addr, null, mbs);
cs.start();
Exemple de création et d’enregistrement d’un connecteur serveur dans un MBean Server
MBeanServer mbs = MBeanServerFactory.createMBeanServer();
JMXServiceURL addr = new JMXServiceURL("jmxmp", null, 0);
JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(addr, null, null);
ObjectName csName = new ObjectName(":type=cserver,name=mycserver");
mbs.registerMBean(cs, csName);
cs.start();
JMX définit également comment un agent peut publier son serveur de connexion dans une infrastructure de recherche et de découverte ; ce qui permet à l’API cliente distante de savoir où trouver un serveur et ainsi de pouvoir si connecter. Cela couvre :
- SLP (Service Location Protocol) en décrivant comme un agent enregistre le service URL d’un connecteur serveur avec SLP
- Jini en décrivant comment un agent enregistre un stub du connecteur serveur dans le service de recherche Jini
- JNDI (Java Naming and Directory Interface) en décrivant un agent enregistre le service URL d’un connecteur dans un annuaire LDAP
Le connecteur serveur est, en outre, capable d’authentifier le client distant. Par exemple, pour le connecteur RMI, cela est fait fournissant une implémentation de l’interface JMXAuthenticator
lors de la création du connecteur serveur. Dans le cas du connecteur JMXMP, cela est fait via SASL. Dans ces deux cas, le résultat de l’authentification renvoie un Subject JAAS qui représente l’identité authentifiée. Les requêtes alors reçues du client sont exécutées en utilisant cette identité. Avec JAAS, il est possible de définir les permissions liées à une identité. En particulié, il est possible de restreindre l’accès aux opérations du MBean Server en utilisant la classe MBeanPermission
. Bien sûr, pour que cela fonctionne, il est nécessaire d’avoir un SecurityManager
. Dans le cas où le connecteur serveur ne supporte pas l’authentification ou qu’il n’est pas configuré, les requêtes clientes sont exécutées en utilisant la même identité que celle qui a été créée avec le connecteur serveur. Comme alternative à JAAS, il est possible de controler l’accès aux opérations du MBean Server en utilisant un MBeanServerForwarder
. Cet objet est une implémentation de l’interface MBeanServer
et transmet les méthodes à un autre objet MBeanServer
mais en ajoutant des opérations avant et après la transmission. Cela permet, en l’occurrence d’y faire des controles d’accès. Pour ajouter un MBeanServerForwarder
, la méthode setMBeanServerForwarder
peut être utilisée. De plus, pour chaque connexion à un connecteur serveur, au moins un Subject authentifié est néccessaire. Cela signifie que si un client effectue des opérations qui nécessitent plusieurs identités, des connexions différentes doivent être établies. Cependant, il est possible aux connecteurs (tels que les connecteurs RMI et JMXMP) d’utiliser la notion de délégation de Subject. Pour ce faire, avec chaque requête, le client spécifie un Subject. La requête est alors exécutée en utilisant une identité pour chaque requête si cela est possible. La permission a utilisé doit alors être de type SubjectDelegationPermission
. Dans ce cas, pour chaque Subject délégué, le client obtient un MBeanServerConnection
du JMXConnector pour un Subject authentifié. Les requêtes utilisées par le MBeanServerConnection
sont émises avec un Subject délégué. Il est, de plus, à noter que ces objets de type MBeanServerConnection
peuvent être obtenus du même JMXConnector et peuvent être utilisés simultanément. Ainsi, pour résumer, il est possible de configurer les permissions d’un connecteur serveur de deux manières :
- toutes les permissions pour les opérations de chaque client distant doivent être configurées,
- un
SubjectDelegationPermission
pour chaquePrincipal
utilisé par les clients distants doit être configuré.
Le connecteur JMXMP est une configuration particulière du connecteur générique où le protocole de transport s’appuie sur TCP et l’encapsulation des objets est la sérialisation native Java. |
Le mot de la fin
Voilà, ce dernier article met fin à cette série. Si vous avez réussi à tenir jusque là et à tout lire, félicitation! Maintenant, vous devriez avoir (enfin, j’espère) une vision plus précise sur ce que contiennent les spécifications JMX. Bien sûr, cette série n’était qu’un condensée (qui vaut ce qu’il vaut) permettant de comprendre les concepts sans pour autant lire les 290 pages de spécification et ne se veut pas être suffisante pour tout maîtriser.