Comment se connecter aux instances Java tournant sur EC2 en utilisant JMX

nous avons des problèmes de connexion à nos applications Java qui fonctionnent dans le cluster EC2 D'Amazon. Nous avons définitivement autorisé à la fois le port" JMX "(qui est habituellement le port de registre RMI) et le port serveur (qui fait la plupart du travail) au groupe de sécurité pour les instances en question. Jconsole se connecte mais semble pendre et ne jamais montrer aucune information.

nous exécutons notre java avec quelque chose comme ceci:

java -server -jar foo.jar other parameters here > java.log 2>&1

nous avons essayé:

  • Telnets pour les ports se connecter , mais aucune information n'est affichée.
  • nous pouvons exécuter jconsole sur l'instance elle-même en utilisant remote-X11 sur ssh et il se connecte et affiche des informations. Ainsi, le JRE est l'exportant localement.
  • ouverture de tous les ports du groupe de sécurité. Weeee.
  • à l'Aide de tcpdump pour s'assurer que le trafic ne va pas à d'autres ports.
  • simulant localement. Nous pouvons toujours nous connecter à nos JREs locaux ou à ceux tournant ailleurs sur notre réseau en utilisant les mêmes paramètres d'application.

java -version sorties:

OpenJDK Runtime Environment (IcedTea6 1.11.5) (amazon-53.1.11.5.47.amzn1-x86_64)
OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode)

mis de côté, nous utilisons mon package Simple JMX qui nous permet de mettre à la fois le registre RMI et les ports serveurs qui sont généralement choisis de manière semi-aléatoire par le registre RMI. Vous pouvez également forcer avec quelque chose comme le JMX URI suivant:

service:jmx:rmi://localhost:" + serverPort + "/jndi/rmi://:" + registryPort + "/jmxrmi"

de nos jours, nous utilisons le même port pour le serveur et le registre. Dans le passé, nous avons utilisé X comme port-registre et X+1 pour le port-serveur pour rendre les règles de groupe de sécurité faciles. Vous vous connectez au port de Registre dans jconsole ou quel que soit le client JMX que vous utilisez.

23
demandé sur Gray 2012-12-06 03:48:09

4 réponses

nous avons des problèmes de connexion à nos applications Java qui fonctionnent dans le cluster EC2 D'Amazon.

il s'avère que le problème était une combinaison de deux réglages manquants. La première force la JRE à préférer ipv4 et et non v6. C'était nécessaire (je suppose) puisque nous essayons de nous y connecter via une adresse v4:

-Djava.net.preferIPv4Stack=true

le vrai bloqueur était le fait que JMX fonctionne par tout d'abord contacter le port RMI qui répond avec le nom d'hôte et le port pour que le client JMX se connecte. Sans paramètres supplémentaires, il utilisera L'adresse IP locale de la boîte qui est une adresse virtuelle 10.X.X.X vers laquelle un client distant ne peut pas se diriger. Nous avions besoin d'ajouter le paramètre suivant qui est le externe nom d'hôte ou IP du serveur -- dans ce cas, c'est le nom d'hôte élastique du serveur.

-Djava.rmi.server.hostname=ec2-107-X-X-X.compute-1.amazonaws.com

Le truc, si vous essayez d'automatiser vos instances EC2 (et pourquoi diable ne le feriez-vous pas), est de trouver cette adresse à l'exécution. Pour ce faire, vous devez mettre quelque chose comme ce qui suit dans notre script de démarrage d'application:

# get our _external_ hostname
RMI_HOST=`wget -q -O - http://169.254.169.254/latest/meta-data/public-hostname`
...
java -server \
    -Djava.net.preferIPv4Stack=true -Djava.rmi.server.hostname=$RMI_HOST \
    -jar foo.jar other parameters here > java.log 2>&1

Le mystérieux 169.254.169.254 la propriété intellectuelle dans le "151950920 de la commande" ci-dessus fournit des informations que l'instance EC2 pouvez demander à propos de lui-même. Je suis déçu que cela ne pas inclure des étiquettes qui sont seulement disponible dans un appel authentifié.

j'utilisais initialement l'adresse ipv4 externe, mais il semble que le JDK essaie d'établir une connexion avec le port serveur quand il démarre. S'il utilise L'IP externe, cela ralentit le temps de démarrage de notre application jusqu'à ce que cela s'arrête. Le nom d'hôte public se résout localement à l'adresse 10-net et au public-ipv4 extérieurement. L'application démarre donc maintenant rapidement et les clients JMX fonctionnent toujours. Woo hoo!

J'espère que ça aidera quelqu'un d'autre. M'a coûté 3 heures aujourd'hui.

pour forcer votre serveur JMX à démarrer le serveur et le registre RMI sur les ports désignés afin que vous puissiez les bloquer dans les groupes de sécurité EC2, voir cette réponse:

Comment fermer rmiregistry en cours d'exécution sur port particulier?

Edit:

ce problème vient de se reproduire. Il semble que le code Java JMX effectue des recherches sur le nom d'hôte de la boîte et les utilise pour essayer de se connecter et de vérifier la connexion JMX.

la question semble être une exigence que le nom d'hôte local de la boîte devrait résoudre au local-ip de la boîte. Par exemple , si votre /etc/sysconfig/network contient HOSTNAME=server1.foobar.com , alors si vous faites une recherche DNS sur server1.foobar.com , vous devriez vous rendre à l'adresse virtuelle 10-NET. Nous nous produisions notre propre fichier /etc/hosts et le nom d'hôte local manquait dans le fichier. Cela a provoqué une pause de nos applications au démarrage ou pas du tout.

enfin

une façon de simplifier votre création JMX est d'utiliser mon package SimpleJMX .

36
répondu Gray 2017-05-23 12:34:27

Par la deuxième réponse Pourquoi ne JMX connexion à Amazon EC2 échec? , la difficulté ici est que par défaut le port RMI est sélectionné au hasard, et les clients ont besoin d'accéder à la fois aux ports JMX et RMI. Si vous utilisez jdk7u4 ou plus tard, le port RMI peut être spécifié via une propriété app. Démarrer mon serveur avec les paramètres JMX suivants a fonctionné pour moi:

sans authentification:

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=9999 
-Dcom.sun.management.jmxremote.rmi.port=9998 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.authenticate=false 
-Djava.rmi.server.hostname=<public EC2 hostname>

avec authentification:

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=9999 
-Dcom.sun.management.jmxremote.rmi.port=9998 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.authenticate=true 
-Dcom.sun.management.jmxremote.password.file=/path/to/jmxremote.password
-Djava.rmi.server.hostname=<public EC2 hostname>

j'ai également ouvert les ports 9998-9999 dans le groupe de sécurité EC2 pour mon exemple.

12
répondu mmindenhall 2017-05-23 12:18:02

une approche légèrement différente en utilisant des tunnels SSH

  1. (sur la machine distante) passer les drapeaux suivants à la JVM

-Dcom.sun.management.jmxremote.port=1099 -Djava.net.preferIPv4Stack=true -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=127.0.0.1

  1. (sur la machine distante) vérifier quels ports java a commencé à utiliser

netstat -tulpn | grep java

tcp 0 0 0.0.0.0:37484 0.0.0.0:* LISTEN 2904/java tcp 0 0 0.0.0.0:1099 0.0.0.0:* LISTEN 2904/java tcp 0 0 0.0.0.0:45828 0.0.0.0:* LISTEN 2904/java

  1. (sur la machine locale) faire SSH tunnels pour tous les ports

ssh -N -L 1099:127.0.0.1:1099 ubuntu@<ec2_ip> ssh -N -L 37484:127.0.0.1:37484 ubuntu@<ec2_ip> ssh -N -L 45828:127.0.0.1:45828 ubuntu@<ec2_ip>

  1. (sur la machine locale) connectez par Java Mission Control à "localhost: 1099"
4
répondu Tim 2018-04-25 23:36:08

la réponse donnée par Gray a fonctionné pour moi, cependant je trouve que je dois ouvrir les ports TCP 0 à 65535 ou je n'entre pas. J' penser que vous pouvez vous connecter sur le principal port JMX, et puis un autre attribué. Je l'ai obtenu de ce billet de blog qui a toujours bien fonctionné pour moi.

1
répondu Eric Pugh 2013-03-21 01:46:50