Remote-JMX-Verbindung

96

Ich versuche, eine JMX-Verbindung zu einer Java-Anwendung herzustellen, die auf einem Remotecomputer ausgeführt wird.

Die Anwendungs-JVM wird mit den folgenden Optionen konfiguriert:

  • com.sun.management.jmxremote
  • com.sun.management.jmxremote.port = 1088
  • com.sun.management.jmxremote.authenticate = false
  • com.sun.management.jmxremote.ssl = false

Ich kann eine Verbindung localhost:1088mit jconsole oder jvisualvm herstellen. Ich kann jedoch keine Verbindung xxx.xxx.xxx.xxx:1088von einem Remotecomputer aus herstellen.

Es gibt keine Firewall zwischen den Servern oder auf dem Betriebssystem. Aber um diese Möglichkeit auszuschließen, telnet xxx.xxx.xxx.xxx 1088denke ich, dass es eine Verbindung herstellt, wenn der Konsolenbildschirm leer wird.

Beide Server sind Windows Server 2008 x64. Versucht mit 64-Bit-JVM und 32-Bit, beide funktionieren nicht.

Lineal
quelle
1
Wahrscheinlich im Zusammenhang mit stackoverflow.com/questions/151238/…
tuler
Hier ist eine detaillierte Anleitung stackoverflow.com/a/11654322/99834
Sorin

Antworten:

117

Wäre es unter Linux gewesen, wäre das Problem, dass localhost die Loopback-Schnittstelle ist. Sie müssen eine Anwendung verwenden, um sich an Ihre Netzwerkschnittstelle zu binden .

Mit netstat können Sie bestätigen, dass es nicht an die erwartete Netzwerkschnittstelle gebunden ist.

Sie können dies zum Laufen bringen, indem Sie das Programm mit dem Systemparameter java.rmi.server.hostname="YOUR_IP"entweder als Umgebungsvariable oder mit aufrufen

java -Djava.rmi.server.hostname=YOUR_IP YOUR_APP
takete.dk
quelle
7
Vergessen Sie nicht hostname -i, siehe stackoverflow.com/a/11654322/99834 für Details.
Sorin
Hat funktioniert! In unserer Umgebung verwenden wir virtuelle VMWare-Maschinen. Der Server befand sich auf einer VM. Die VM wurde eingezäunt bereitgestellt, sodass sie interne und externe IP-Adressen hat. Wir haben den Server-Java-Prozess mit -Djava.rmi.server.hostname = <externe-IP-Adresse> gestartet.
Buzz3791
Um die Host-IP festzulegen oder die lokale Host-IP zu ändern, wäre dieser Link hilfreich.
Reza Ameri
Ich habe hier zwei Fragen: 1) Was ist, wenn man JMXMP anstelle von JMX verwenden möchte? Was wären die Konfigurationen dafür? und 2) Ist es möglich, die JMX-Verbindung herzustellen, ohne das RMI-Protokoll zu laden?
Kumar Vaibhav
64

Ich habe mehr als einen Tag damit verbracht, JMX dazu zu bringen, von außerhalb von localhost zu arbeiten. Es scheint, dass SUN / Oracle diesbezüglich keine gute Dokumentation geliefert hat.

Stellen Sie sicher, dass der folgende Befehl eine echte IP oder einen echten Hostnamen zurückgibt. Wenn es etwas wie 127.0.0.1, 127.0.1.1 oder localhost zurückgibt, funktioniert es nicht und Sie müssen die /etc/hostsDatei aktualisieren .

hostname -i

Hier ist der Befehl, der benötigt wird, um JMX auch von außen zu aktivieren

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.port=1100
-Djava.rmi.server.hostname=myserver.example.com

Wo, wie Sie angenommen haben, muss myserver.example.com mit den zurückgegebenen Ergebnissen übereinstimmen hostname -i.

Natürlich müssen Sie sicher sein, dass die Firewall Sie nicht blockiert, aber ich bin mir fast sicher, dass dies nicht Ihr Problem ist. Das Problem ist der letzte Parameter, der nicht dokumentiert ist.

Sorin
quelle
Das Hinzufügen von -Djava.rmi.server.hostname = myserver.example.com hat den Trick gemacht! Vielen Dank!
Jim Bethancourt
Ich habe mir erlaubt,
Klara
2
"Stellen Sie sicher, dass der folgende Befehl eine echte IP oder einen echten Hostnamen zurückgibt. Wenn er etwas wie 127.0.0.1, 127.0.1.1 oder localhost zurückgibt, funktioniert er nicht und Sie müssen die Datei / etc / hosts aktualisieren." Was?
PedroD
1
Nur schnell nicht, die java.rmi.server.hostname=<Public DNS name from AWS EC2 console for the instance>. Hoffe das hilft jemandem.
Sonny
24

Bei meinen Tests mit Tomcat und Java 8 hat die JVM zusätzlich zu dem für JMX angegebenen einen kurzlebigen Port geöffnet. Der folgende Code hat mich repariert; Probieren Sie es aus, wenn Sie Probleme haben, bei denen Ihr JMX-Client keine Verbindung herstellt (z. B. VisualVM) .

-Dcom.sun.management.jmxremote.port=8989
-Dcom.sun.management.jmxremote.rmi.port=8989

Siehe auch Warum Java 3 Ports öffnet, wenn JMX konfiguriert ist?

LeslieM
quelle
12

http://blogs.oracle.com/jmxetc/entry/troubleshooter_connection_problems_in_jconsole

Wenn Sie versuchen, auf einen Server zuzugreifen, der sich hinter einem NAT befindet, müssen Sie Ihren Server höchstwahrscheinlich mit dieser Option starten

-Djava.rmi.server.hostname=<public/NAT address>

Damit enthalten die an den Client gesendeten RMI-Stubs die öffentliche Adresse des Servers, sodass die Clients von außen darauf zugreifen können.

h0nIg
quelle
8

Es scheint, dass Ihr Endzitat zu früh kommt. Es sollte nach dem letzten Parameter sein.

Dieser Trick hat bei mir funktioniert.

Mir ist etwas Interessantes aufgefallen: Wenn ich meine Anwendung über die folgende Befehlszeile starte:

java -Dcom.sun.management.jmxremote.port=9999
     -Dcom.sun.management.jmxremote.authenticate=false
     -Dcom.sun.management.jmxremote.ssl=false

Wenn ich versuche, mit jconsole von einem Remotecomputer aus eine Verbindung zu diesem Port herzustellen, ist die TCP-Verbindung erfolgreich. Einige Daten werden zwischen der Remote-jconsole und dem lokalen jmx-Agenten ausgetauscht, auf dem meine MBean bereitgestellt wird. Anschließend zeigt jconsole eine Verbindungsfehlermeldung an. Ich habe eine Wireshark-Erfassung durchgeführt, die den Datenaustausch sowohl vom Agenten als auch von der Jconsole zeigt.

Daher ist dies kein Netzwerkproblem. Wenn ich ein netstat -an mit oder ohne Systemeigenschaft java.rmi.server.hostname ausführe, habe ich die folgenden Bindungen:

 TCP    0.0.0.0:9999           0.0.0.0:0              LISTENING
 TCP    [::]:9999              [::]:0                 LISTENING

Dies bedeutet, dass in beiden Fällen der an Port 9999 erstellte Socket Verbindungen von einem beliebigen Host an einer beliebigen Adresse akzeptiert.

Ich denke, der Inhalt dieser Systemeigenschaft wird irgendwo bei der Verbindung verwendet und mit der tatsächlichen IP-Adresse verglichen, die der Agent für die Kommunikation mit jconsole verwendet. Und wenn diese Adressen nicht übereinstimmen, schlägt die Verbindung fehl.

Ich hatte dieses Problem nicht, als ich mit jconsole vom selben Host aus eine Verbindung herstellte, sondern nur von echten physischen Remote-Hosts. Ich nehme also an, dass diese Überprüfung nur durchgeführt wird, wenn die Verbindung von "außen" kommt.

yohann.martineau
quelle
Was meinst du mit "dein Endzitat kommt zu früh"? Ich habe das gleiche Problem, ich sehe, dass die TCP-Verbindung hergestellt wird, aber schließlich behauptet jconsole, dass keine Verbindung hergestellt werden konnte.
Tsuna
Ich weiß nicht, ob ich mich richtig erinnere, dass irgendwo ein Zitat offen war und dieses Zitat nicht am Ende der Parameter stand. Vielleicht war es in einem Batch-Skript, ich kann mich nicht erinnern. Aber ich muss zugeben, dass diese Antwort in Bezug auf die Frage keinen Sinn ergibt ... Vielleicht wurde die Frage bearbeitet? Keine bearbeitete Benachrichtigung unter der Frage ... Ich weiß nicht, es tut mir leid.
yohann.martineau
6

Für mich funktionierte es, / etc / hosts so einzustellen, dass der Hostname auf die IP und nicht auf die Loopback-Schnittstelle verweist, und dann meine Anwendung neu zu starten.

Katze / etc / Hosts

127.0.0.1      localhost.localdomain localhost
192.168.0.1    myservername

Dies ist meine Konfiguration:

-Dcom.sun.management.jmxremote.port=1617 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.authenticate=false
Maoz Zadok
quelle
5

Vielen Dank, es funktioniert so:

java -Djava.rmi.server.hostname = xxx.xxx.xxx.xxx -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.ssl = false -Dcom.sun.management.jmxremote.authenticate = false - Dcom.sun.management.jmxremote.port = 25000 -jar myjar .jar

user3406690
quelle
0

Ich habe das gleiche Problem und ändere jeden Hostnamen, der mit dem lokalen Hostnamen übereinstimmt, in 0.0.0.0. Danach scheint es zu funktionieren.

ianpojman
quelle
0

Um JMX Remote zu aktivieren, übergeben Sie die folgenden VM-Parameter zusammen mit JAVA Command.

    -Dcom.sun.management.jmxremote 
    -Dcom.sun.management.jmxremote.port=453
    -Dcom.sun.management.jmxremote.authenticate=false                               
    -Dcom.sun.management.jmxremote.ssl=false 
    -Djava.rmi.server.hostname=myDomain.in
Ajay Kumar
quelle
1
Können Sie mir sagen, warum es für 0.0.0.0 und nicht für eine bestimmte IP bindend ist
Babu James
0

Versuchen Sie dies, ich habe getestet, um auf JMX im Docker-Container zuzugreifen

-Dcom.sun.management.jmxremote = true -Djava.rmi.server.hostname = localhost -Dcom.sun.management.jmxremote.port = 16000 -Dcom.sun.management.jmxremote.rmi.port = 16000 -Dcom.sun .management.jmxremote.authenticate = false -Dcom.sun.management.jmxremote.ssl = false

Dann

$ jconsole localhost: 16000

Emmerson
quelle
-11

Versuchen Sie, Ports höher als 3000 zu verwenden.

darko.topolsek
quelle