JConsole verbindet sich mit der Registry, dann schickt RMI sie woandershin
Dass der Registry-Port antwortet, ist nur der erste Sprung. Ein entfernter JMX-Server kann einen anderen Host und einen anderen Connector-Port ankündigen, und der Tunnel muss beide erreichen.
Verbinde dich über den Tunnel mit dem Registry-Port, beobachte den beginnenden Handshake und sieh dann zu, wie JConsole trotzdem in einen Timeout läuft. Das passiert, weil die erste TCP-Verbindung nicht die Management-Verbindung ist, sondern ein Lookup. Die RMI-Registry antwortet mit einer Referenz, die einen Host und einen zweiten Port benennt, und JConsole geht anschließend dorthin, wohin man sie geschickt hat. Erreicht der Tunnel nur den ersten Port des Servers, oder benennt die Referenz eine Adresse, die nur im LAN des Servers selbst existiert, bleibt der Client hängen, nachdem er scheinbar erfolgreich war.
Der Mythos: ein offener Port ist eine Verbindung
Remote-JMX über RMI umfasst mindestens zwei Endpunkte, und sie werden von unterschiedlichen Teilen des Systems ausgewählt. Der Registry-Port ist der, den du im Client eintippst, und er existiert, um den Stub auszugeben, der den eigentlichen Connector beschreibt. Den ersten erfolgreichen Socket als Beweis dafür zu nehmen, dass der Management-Pfad offen ist, verwandelt eine Zwei-Minuten-Diagnose in einen Nachmittag voller Firewall-Tickets.
Achte auf den Fehler des Clients selbst statt auf die Listener-Liste des Servers. Ein Fehler, nachdem der Handshake begonnen hat, sagt dir, dass die zweite Verbindung nicht zustande kam, nicht die erste.
Was die Registry zurückgibt
Der Stub enthält eine Adresse und einen Port, serialisiert in dem Moment, in dem der Connector erstellt wurde. Auf einem Server mit mehreren Schnittstellen hat der Stack womöglich eine Adresse gewählt, die aus dem lokalen Netz erreichbar und aus deinem nicht erreichbar ist. Der Client kennt den Unterschied nicht; er wählt einfach den Wert, den er bekommen hat, und das Paket folgt der Route, die für diese Adresse existiert, auf einem VPN-Client oft gar keiner. Das ist der Moment, in dem die zweite Verbindung versucht wird.
Das ist auch der Grund, warum der Fehler je nach Umgebung sporadisch auftritt: Derselbe Server kann sich für einen Nutzer im LAN und einen Nutzer im Tunnel unterschiedlich verhalten, ohne dass sich an der JMX-Konfiguration irgendetwas ändert.
Zwei Ports und zwei Eigenschaften, die sie festnageln
Der Registry-Port kommt von com.sun.management.jmxremote.port, und der Connector lässt sich mit com.sun.management.jmxremote.rmi.port festnageln, statt ihn dem Stack zu überlassen. Setze beide ausdrücklich, wenn eine Firewall oder eine Security Group zwischen Client und Server liegt, denn ein unvorhersehbarer zweiter Port lässt sich nicht vorab freigeben, und ein breites Portband, das man dafür öffnet, ist schlimmer als ein fester Wert.
Prüfe dann mit ss -ltn oder netstat -an auf dem Server, ob beide Ports lauschen und auf welchen Adressen. Ein Listener, der an Loopback gebunden ist, ist für ein rein lokales Deployment richtig und für dieses hier nutzlos.
Wenn der angekündigte Name falsch ist
Der Hostname in der entfernten Referenz wird durch java.rmi.server.hostname gesetzt. Er beeinflusst, was der Stub ankündigt; er ist für sich genommen keine Anweisung, jeden Listener an eine Schnittstelle zu binden, weshalb das Setzen nicht immer das erwartete Ein-Port-Verhalten erzeugt. Setze ihn, starte den Prozess neu und prüfe dann, was der Stub tatsächlich enthält. Wähle einen Namen oder eine Adresse, die der Client auflösen und durch den Tunnel erreichen kann, und starte den Prozess neu, damit der Stub neu aufgebaut wird.
Container-Netzwerke machen das schlimmer, weil die Adresse, die der Prozess sieht, eine interne sein kann, die von außerhalb des Containers nicht geroutet wird. Veröffentliche den gewünschten Hostnamen ausdrücklich, statt ihn der Plattform zu überlassen.
Wenn du statt eines VPN einen SSH-Tunnel verwendest, erscheint dasselbe Problem in anderem Gewand: Nur den Registry-Port weiterzuleiten lässt den zweiten Endpunkt auf eine Adresse zeigen, die dein Client nicht erreichen kann. Leite beide Ports weiter und sorge dafür, dass der angekündigte Name auf etwas auflöst, das der Client lokal erreicht.
Schalte die Management-Sicherheit nicht ab, um es zu vereinfachen
Snippets, die Authentifizierung und TLS abschalten, sind leicht zu finden und bringen die Verbindung auf eine Weise zum Laufen, die du später rückgängig machen musst. Remote-JMX ist eine Management-Schnittstelle mit denselben Rechten wie der Prozess, den sie inspiziert; behalte ihre Zugriffskontrollen bei, und wenn der Client keine Anmeldedaten vorweisen kann, behebe das stattdessen.
Wenn die Endpunkte stimmen, bewahre den nächsten Fehler auf, den du siehst. Eine Ablehnung durch Truststore oder Konto kommt später als ein unerreichbarer Connector und bedeutet, dass die Netzwerkarbeit erledigt ist.