Domanda

La mia domanda specifica ha a che fare con JMX utilizzato in JDK 1.6:se io sono in esecuzione un processo Java utilizzando JRE 1.6 con

com.sun.management.jmxremote

nella riga di comando, non Java scegliere una porta di default per il remoto JMX connessioni?

Antefatto:Attualmente sto cercando di sviluppare una procedura per dare ad un cliente che potrà consentire loro di connettersi ad uno dei nostri processi tramite JMX da una macchina remota.L'obiettivo è quello di facillitate loro il debug remoto di una situazione che si verificano su una visualizzazione in tempo reale della console.A causa del loro contratto di servizio, sono fortemente motivati ad acquisire più dati possibili e, se la situazione sembra troppo complicato da risolvere in fretta, per riavviare la console di visualizzazione e consentire di riconnettersi al server-side.

Sono consapevole del riuscivo a correre jconsole su JDK 1.6 i processi e jvisualvm sul post-JDK 1.6.7 processi dato accesso fisico alla console.Tuttavia, a causa delle esigenze operative e dei problemi della gente coinvolta, siamo fortemente motivati a prendere i dati di cui abbiamo bisogno in remoto e ottenere loro e in esecuzione di nuovo.

EDIT:Sono consapevole della riga di comando di proprietà della porta

com.sun.management.jmxremote.port=portNum

La domanda che sto cercando di risposta è, se non si imposta la proprietà della riga di comando, non Java, scegli un'altra porta per il monitoraggio remoto?Se è così, come si fa a determinare che cosa potrebbe essere?

È stato utile?

Soluzione

Il documentazione suggerisce che l'agente di JMX utilizza un locale porta-qualcosa di irraggiungibile dall'esterno della macchina, a meno di non specificare le seguenti proprietà:

com.sun.management.jmxremote.port=portNum

Questo è per motivi di sicurezza, nonché per la ragione data da Mr Potato Head.Così, sembra che Java 6 non aprire un default accessibile in remoto porta per JMX.

EDIT:Aggiunto dopo l'OP aggiunto una risposta con ulteriori informazioni.

Un'altra opzione è, in qualche modo creare un proxy locale che ascolta tutti i locali JMX connessioni e le esportazioni di queste informazioni.In questo modo, non è necessario disporre di tale magia di configurazione di ogni istanza della JVM sul server.Invece il proxy locale può connettersi a tutte le Jvm via JMX e quindi in qualche modo esporre queste informazioni in remoto.Io non sono positivo esattamente come si potrebbe implementare questo, ma qualcosa di simile a questo può essere meno lavoro di quello che altrimenti di avere a che fare per esporre tutte le Jvm in remoto tramite JMX.

Altri suggerimenti

Per quanto ne so,

Qui ci sono le possibilità per il collegamento di un JMX processo client (un applicazione per la gestione di come jconsole, jmxterm, mc4j, jvmstat, jmxmonitor, jps, ...) per un JMX processo server (il agente).

Il protocollo di collegamento JMX client e JMX server è presupposto per essere 'Java RMI' (aka 'RMI-JRMP').Questo dovrebbe essere il default.Si può configurare altri protocolli, in particolare 'RMI-IIOP' e 'JMXMP'.Protocolli speciali sono possibili:il MX4J progetto per esempio fornisce inoltre SOAP/HTTP e vari protocolli di serializzazione su HTTP.

Fare riferimento a Sun/Oracle docs per i dettagli sulla configurazione.

Anche un'occhiata al file jre/lib/management/management.properties nel JDK di distribuzione.

Così, la possibilità di:

Case 0:La JVM è avviato senza alcuna configurazione particolare

Prima Di Java 6:La JVM non si comporta come un JMX server.Qualsiasi programma che viene eseguito all'interno della JVM può accedere della JVM MBeanServer a livello di programmazione e usarlo per interessanti scambi di dati tra thread o fare il monitoraggio JVM, ma non di gestione da al di fuori della JVM processo è possibile.

Dato Che Java 6:Anche se non esplicitamente configurato, si può accedere JMX funzionalità della JVM locale (dalla stessa macchina), come descritto nel "Caso 1".

Caso 1:La JVM è iniziato con -Dcom.sun.management.jmxremote

La JVM è configurato per funzionare come un locale (la stessa macchina solo) JMX server.

In questo caso (e in linea di principio solo per Sun/Oracle Jvm) un JMX client può connettersi al JMX server tramite file mappati in memoria trovati in /tmp/hsperfdata_[user].Questa è accennato, il Sole documentazione e denominata "locale di monitoraggio" (e anche il Allegare API).Non funziona su filesystem FAT, come le autorizzazioni non possono essere impostati correttamente, c'.Vedere questo blog.

Sun consiglia di esecuzione jconsole su una macchina separata dal JMX server jconsole a quanto pare è un maiale di risorse, in modo che questo "monitoraggio" e la cosa non è necessariamente una buona idea.

Monitoraggio locale è, tuttavia, piuttosto sicuro, essere utilizzabile solo a livello locale e di essere facilmente controllato tramite permessi del file system.

Caso 2:JMX server è iniziato con -Dcom.sun.management.jmxremote.port=[rmiregistryport]

La JVM è configurato per funzionare come un JMX server in ascolto su diverse porte TCP.

La porta specificata sulla riga di comando saranno assegnati dalla JVM e un registro RMI saranno disponibili.Il registro di sistema pubblicizza un connettore denominato 'jmxrmi'.Punti al secondo, assegnati in modo casuale porta TCP (un 'effimera' porto) su cui il JMX RMI server è in ascolto e attraverso il quale effettivo scambio di dati avviene.

Locali, come descritto in 'Caso 1' è sempre attivata in Caso di 2'.

JMX server è in ascolto su tutte le interfacce di default, quindi è possibile connettersi (e il controllo) da locale di collegamento a 127.0.0.1:[rmiregistryport] come ben si collega in remoto a [qualsiasi indirizzo IP esterno]:[porto] in remoto.

Questo implica che è necessario per guardare le implicazioni per la sicurezza.Si può fare la JVM ascoltare su 127.0.0.1:[rmiregistryport] solo attraverso la creazione di -Dcom.sun.management.jmxremote.local.only=true.

Piuttosto è un peccato che non si può specificare dove la porta effimera saranno assegnati - si è sempre scelto in modo casuale all'avvio.Questo può anche significare che il firewall deve diventare il formaggio svizzero dei dannati!Tuttavia, ci sono soluzioni alternative.In particolare, Apache Tomcat imposta effimero JMX RMI server porta via la sua JMX Remoto Listener del Ciclo di vita.Il codice per eseguire questo po ' di magia può essere trovato alla org.apache.catalina.mbeans.JmxRemoteLifecycleListener.

Se si utilizza questo metodo, si potrebbe anche verificare che:

  1. JMX client di autenticazione per le JMX server
  2. Il TCP scambio tra il client e il server è crittografato con SSL

Come quello che si fa è descritto in il Sun/Oracle documentazione

Altri approcci

Si possono fare interessanti permutazioni per evitare di dover usare il protocollo RMI.In particolare, si potrebbe aggiungere un servlet engine (come Jetty) per il proprio processo.Quindi aggiungere i servlet che tradurre alcuni HTTP scambio internamente in diretta accessi della JVM MBeanServer.Si sarebbe quindi in caso di 0' ma hanno ancora la capacità di gestione, possibilmente attraverso un codice HTML interfaccia.Il JBoss JMX Console è un esempio di questo.

Più off-topic, si potrebbe utilizzare SNMP direttamente (cosa che non ho mai provato) secondo questo documento.

Mostrare e Raccontare il Tempo

E ora è il momento per un po ' di codice per illustrare un JXM di cambio.Prendiamo ispirazione da un Sunoracle tutorial.

Questo funziona su Unix.Usiamo una JVM che è configurato come un JMX server utilizzando:

-Dcom.sun.management.jmxremote.port=9001

Usiamo lsof per controllare quali porte TCP si tiene aperto:

lsof -p <processid> -n | grep TCP

Si dovrebbe vedere qualcosa di simile a questo, il registro di sistema porta e la porta effimera:

java    1068 user  127u  IPv6 125614246                 TCP *:36828 (LISTEN)
java    1068 user  130u  IPv6 125614248                 TCP *:9001  (LISTEN)

Usiamo tcpdump per ispezionare lo scambio di pacchetti tra JMX client e JMX server:

tcpdump -l -XX port 36828 or port 9001

Abbiamo impostato il backup di un file .java.policy nella home directory per consentire il cliente di connettersi in remoto:

grant {
    permission java.net.SocketPermission 
    "<JMX server IP address>:1024-65535", "connect,resolve";
};

E quindi siamo in grado di eseguire questo e vedere cosa succede:

package rmi;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import javax.management.remote.rmi.RMIConnection;
import javax.management.remote.rmi.RMIServer;

public class Rmi {

    public static void main(String args[]) throws Exception {
        // We need a Security Manager (not necessarily an RMISecurityManager)
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
        //
        // Define a registry (this is just about building a local data structure)
        // 
        final int comSunManagementJmxRemotePort = 9001;
        Registry registry = LocateRegistry.getRegistry("<JMX server IP address>", comSunManagementJmxRemotePort);
        //
        // List registry entries. The client connects (using TCP) to the server on the
        // 'com.sun.management.jmxremote.port' and queries data to fill the local registry structure.
        // Among others, a definition for 'jmxrmi' is obtained.
        //
        System.out.print("Press enter to list registry entries");
        System.in.read();
        String[] names = registry.list();
        for (String name : names) {
            System.out.println("In the registry: " + name);
        }
        //
        // 'Looking up' the entry registered under 'jmxrmi' involves opening and tearing down
        // a TCP connection to the 'com.sun.management.jmxremote.port', as well as a TCP
        // connection to an ephemeral secondary port chosen at server startup.
        // The actual object locally obtained is a "javax.management.remote.rmi.RMIServerImpl_Stub"
        // indicating where the ephemeral port is.
        // "RMIServerImpl_Stub[UnicastRef [liveRef: [endpoint:[$IP:$EPHEMERAL_PORT](remote),objID:[-62fb4c1c:131a8c709f4:-7fff, -3335792051140327600]]]]"        
        //
        System.out.print("Press enter to get the 'jmxrmi' stub");
        System.in.read();
        RMIServer jmxrmiServer = (RMIServer)registry.lookup("jmxrmi");
        System.out.println(jmxrmiServer.toString());
        //
        // Now get a "RMI Connection" to the remote. This involves setting up and tearing
        // down a TCP connection to the ephemeral port. 
        //        
        System.out.print("Press enter to get the 'RMIConnection'");
        System.in.read();
        RMIConnection rcon = jmxrmiServer.newClient(null);
        //
        // Ask away. This involves setting up and tearing
        // down a TCP connection to the ephemeral port. 
        //
        System.out.print("Press enter to get the 'domains'");
        System.in.read();
        for (String domain : rcon.getDomains(null)) {
            System.out.println("Domain: " + domain);
        }
        //
        // Ok, that will do. For serious applications, we better use the higher-level JMX classes
        //
    }   
}

In realtà c'è un'privi di documenti di proprietà che è possibile utilizzare per forza JMX creare accessibile in remoto connettori casuale di numeri di porta.

-Dcom.sun.management.jmxremote.authenticate="false" 
-Dcom.sun.management.jmxremote="true" 
-Dcom.sun.management.jmxremote.ssl="false" 
-Dcom.sun.management.jmxremote.port="0"
-Dcom.sun.management.jmxremote.local.only="false"

Ultime due proprietà sono di maggior importanza.

Il documentazione sembra indicare che l'agente di JMX utilizza un locale di porte effimere, a meno che non è possibile specificare le seguenti proprietà:

com.sun.management.jmxremote.port=portNum

Porte di Default sono evitati perché si potrebbe avere molti applicazioni java su un sistema, e se c'era una porta di default, solo una applicazione sarebbe in grado di essere gestiti!La configurazione di cui sopra di proprietà è previsto per il express scopo di remoto di gestione.

Se si deve insistere sull'uso di una porta effimera, quindi l'URL dell'agente di JMX deve essere accessibile dall'interno della JVM, attraverso le seguenti proprietà di sistema (anche se è probabile che questo sia un indirizzo locale):

com.sun.management.jmxremote.localConnectorAddress

Nota:Credo che si potrebbe sempre aprire un socket su una distanza di indirizzi disponibili e le richieste di proxy per il socket locale, ma utilizzando l'opzione disponibile sembra molto più attraente!

Quindi, la risposta alla mia domanda è "no".

Tuttavia, è interessante esaminare il perché.Guarda il netstat uscita da un locale valido connessione.Qui ci sono le porte che vedo aperto, come risultato di un jconsole fare una connessione locale stesso.Come si può vedere, porta 1650 locale è la porta utilizzata per la JMX informazioni:

Proto  Local Address          Foreign Address        State
TCP    Gandalf:1650           Gandalf:1652           ESTABLISHED
TCP    Gandalf:1650           Gandalf:1653           ESTABLISHED
TCP    Gandalf:1650           Gandalf:1654           ESTABLISHED
TCP    Gandalf:1650           Gandalf:1655           ESTABLISHED
TCP    Gandalf:1650           Gandalf:1656           ESTABLISHED
TCP    Gandalf:1652           Gandalf:1650           ESTABLISHED
TCP    Gandalf:1653           Gandalf:1650           ESTABLISHED
TCP    Gandalf:1654           Gandalf:1650           ESTABLISHED
TCP    Gandalf:1655           Gandalf:1650           ESTABLISHED
TCP    Gandalf:1656           Gandalf:1650           ESTABLISHED

Tuttavia, non è sufficiente a provare a connettersi jconsole per localhost:1650.Purtroppo, tutto ciò che è al netto di una "Connessione non riuscita:nessun oggetto nella tabella" messaggio.

Così, la conclusione della mia storia originale è che, se abbiamo intenzione di facilitare il monitoraggio remoto utilizzando JMX per i nostri clienti, abbiamo davvero bisogno di identificare unico individuo, porte di accesso remoto per la varietà di Java processi che vengono avviati nel nostro sistema.Fortunatamente, tutto questo richiede l'uso accorto delle VM argomento:

com.sun.management.jmxremote.port=portNum

dove ci sarà quasi certamente una sequenza di pre-specificato gamma di portNum in modo che il cliente può selezionare la corretta applicazione remota tramite il numero di porta.

Ho lavorato recentemente per capire come abilitare il controllo remoto JMX gestione da codice java, senza richiedere la JVM che sono stati avviati con proprietà speciali set.La soluzione che ho trovato è quello di iniziare il mio privato RMI registro di sistema -- abbastanza facile -- e per esporre il JMX servizio del registro di sistema.Ho creato il mio MBeanServer, quindi creare un nuovo JMXConnectorServer.Il JMXConnectorServer è creato attraverso una chiamata di

connector = JXMConnectorServerFactory.newJMXConnectorServer(url, null, server);

Dove server è il MBeanServer, e l'url è un'istanza di JMXServiceURL.

L'url è nella forma "del servizio:jmx:rmi:///jndi/rmi://localhost:/jmxrmi" dove porta (locale) privato del registro e il numero di porta."jmxrmi" è il nome per il JMX servizio.

Dopo l'impostazione di questo, ed avviare il connettore, ho scoperto che non posso collegarlo da jconsole utilizzando hostname:port.

Questo interamente indirizzi le mie esigenze;Sono curiosa di sapere se qualcuno vede un difetto di questo approccio.

Riferimento: JMX Tutorial, Cap.3

Se vi capita di eseguire l'applicazione all'interno di Glassfish server app, è sufficiente eseguire il seguente asadmin comando, è necessario riavviare tutti i server in esecuzione per la modifica abbia effetto.

./asadmin enable-sicuro-admin

Ci sono extra Glassfish server configurazioni per consentire di sicurezza, vedere di più La connessione remota a Glassfish attraverso JMX.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top