Alguém já colocou um JMX JConsole remoto para funcionar?

120

Parece que nunca fiz isso funcionar no passado. Atualmente, SEI que não funciona.

Mas iniciamos nosso processo Java:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=6002
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

Eu posso telnetar para a porta e "algo está lá" (ou seja, se eu não iniciar o processo, nada responde, mas se eu iniciar, ele inicia), mas não consigo fazer o JConsole funcionar preenchendo o IP e porta.

Parece que deveria ser tão simples, mas sem erros, sem ruído, sem nada. Simplesmente não funciona.

Alguém sabe a dica quente para isso?

Will Hartung
fonte
3
Se você estiver usando o tomcat, esta pode ser a solução: stackoverflow.com/questions/1263991/…
Hajo Thelen
5
Você se esqueceu de aceitar algo aqui @Will?
Cinza,

Respostas:

126

Eu tenho uma solução para isso:

Se o seu processo Java estiver sendo executado no Linux atrás de um firewall e você deseja iniciar o JConsole / Java VisualVM / Java Mission Control no Windows em sua máquina local para conectá-lo à porta JMX do seu processo Java .

Você precisa acessar sua máquina Linux via login SSH. Toda a comunicação será encapsulada pela conexão SSH.

DICA: Esta solução funciona independentemente da existência de firewall ou não.

Desvantagem: sempre que reiniciar o processo java, você precisará executar todas as etapas de 4 a 9 novamente.


1. Você precisa do conjunto de massa para a sua máquina Windows a partir daqui:

http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html

Pelo menos o putty.exe


2. Defina uma porta livre em sua máquina Linux:

<jmx-remote-port>

Exemplo:

jmx-remote-port = 15666      


3. Adicione argumentos para o processo java na máquina Linux

Isso deve ser feito exatamente assim. Se for feito como a seguir, funciona para máquinas Linux atrás de firewalls (funciona por causa do -Djava.rmi.server.hostname=localhostargumento).

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=<jmx-remote-port>
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.local.only=false
-Djava.rmi.server.hostname=localhost

Exemplo:

java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=15666 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=false -Djava.rmi.server.hostname=localhost ch.sushicutta.jmxremote.Main


4. Obtenha a Id do processo de seu processo Java

ps -ef | grep <java-processname>

result ---> <process-id>

Exemplo:

ps -ef | grep ch.sushicutta.jmxremote.Main

result ---> 24321


5. Encontre uma porta arbitrária para download de stubs RMIServer

O processo java abre uma nova porta TCP na máquina linux, onde os Stubs do servidor RMI estarão disponíveis para download. Essa porta também precisa estar disponível por meio do túnel SSH para obter uma conexão com a Java Virtual Machine.

Com netstat -lpesta porta pode ser encontrada também alsof -i dá dicas de qual porta foi aberta do processo java.

NOTA: Esta porta sempre muda quando o processo java é iniciado.

netstat -lp | grep <process-id>

tcp        0      0 *:<jmx-remote-port>     *:*     LISTEN      24321/java
tcp        0      0 *:<rmi-server-port>     *:*     LISTEN      24321/java


result ---> <rmi-server-port>

Exemplo:

netstat -lp | grep 24321

tcp        0      0 *:15666     *:*     LISTEN      24321/java
tcp        0      0 *:37123     *:*     LISTEN      24321/java


result ---> 37123


6. Habilite dois túneis SSH de sua máquina Windows com massa

Source port: <jmx-remote-port>
Destination: localhost:<jmx-remote-port>
[x] Local       
[x] Auto       

Source port: <rmi-server-port>
Destination: localhost:<rmi-server-port>
[x] Local       
[x] Auto

Exemplo:

Source port: 15666
Destination: localhost:15666
[x] Local       
[x] Auto       

Source port: 37123
Destination: localhost:37123
[x] Local       
[x] Auto


Configurações para abrir um túnel SSL via Putty


7. Faça login em sua máquina Linux com Putty com este túnel SSH ativado.

Deixe a sessão de massa aberta.

Quando você estiver logado, o Putty fará um túnel de todas as conexões TCP para a máquina Linux através da porta 22 SSH.

Porta JMX:

Windows machine: localhost:15666   >>> SSH >>>   linux machine: localhost:15666

RMIServer-Stub-Port:

Windows Machine: localhost:37123   >>> SSH >>>   linux machine: localhost:37123


8. Inicie o JConsole / Java VisualVM / Java Mission Control para se conectar ao seu processo Java usando a seguinte URL

Isso funciona, porque o JConsole / Java VisualVM / Java Mission Control pensa que você se conectou a uma porta em sua máquina Windows local. mas Putty envia toda a carga útil para a porta 15666 para sua máquina Linux.

Na máquina linux, primeiro o processo java responde e envia de volta a porta RMIServer. Neste exemplo 37123.

Então JConsole / Java VisualVM / Java Mission Control pensa que se conecta ao localhost: 37123 e o putty enviará toda a carga útil para a máquina Linux

O processo java responde e a conexão é aberta.

[x] Remote Process:
service:jmx:rmi:///jndi/rmi://localhost:<jndi-remote-port>/jmxrmi

Exemplo:

[x] Remote Process:
service:jmx:rmi:///jndi/rmi://localhost:15666/jmxrmi


Conectar via URL do serviço jmx


9. APROVEITE # 8-]

Sushicutta
fonte
1
Só uma pequena pergunta aqui - não é possível fazer uma conexão JMX sem rmi?
Kumar Vaibhav
5
Recebi uma dica de que podemos definir um rmi.port com um número de porta fixo, para que possamos definir a porta arbitrária para download de stubs do RMIServer. isso deve funcionar com a propriedade Java "com.sun.management.jmxremote.rmi.port = <rmi-server-port>". Parece um recurso não documentado no Oracle Java VM.
sushicutta
1
Com certeza é melhor configurar keystores e truststores
TekiusFanatikus
Mesmo processo, mas não tenho esse objeto na tabela
wener
2
@sushicutta você pode adicionar esta dica em sua resposta, está funcionando perfeitamente bem, e pode remover as etapas de 4 a 6, o problema é que sua porta encaminhada deve ser a mesma que a porta original e as portas jmx e rmi também devem seja o mesmo
pobre de
80

Adicionar -Djava.rmi.server.hostname='<host ip>'resolveu esse problema para mim.

época
fonte
2
No meu caso, tenho que adicionar o endereço ip (-Djava.rmi.server.hostname = <ip>). hostname -i me deu dois endereços IP e o correto era o segundo na lista.
Georgy Bolyuba
4
não resolveu o problema para mim. conectar windows-2-windows não é um problema para mim, MAS quando tento me conectar de um JVM Jvisualvm.exe no Windows para monitorar um serviço java em execução no SUSE com Oracle JDK 1.6.024, a conexão falha. Por essa razão, acho que a pergunta dessa pessoa ainda permanece sem resposta.
djangofan,
Isso resolveu o problema para mim. Isso mais o conjunto usual de 3 (autenticar / porta / ssl) e posso conectar remotamente agora. A caixa está ouvindo em várias interfaces virtuais, porém, pode ter sido por que não especificar o host confundiu o jvm.
Nicholi
Finalmente resolvi meus problemas ao conectar o jconsole no meu laptop osx. Obrigado.
rado
Funcionou para mim. Obrigado!
Jeff
58

Tentei com Java 8 e versões mais recentes

Esta solução também funciona bem com firewalls

1. Adicione isso ao seu script de inicialização java no host remoto:

-Dcom.sun.management.jmxremote.port=1616
-Dcom.sun.management.jmxremote.rmi.port=1616
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.local.only=false
-Djava.rmi.server.hostname=localhost

2. Execute no seu computador.

  • Usuários do Windows :

    putty.exe -ssh user@remote-host -L 1616:remote-host:1616

  • Usuários Linux e Mac :

    ssh user@remote-host -L 1616:remote-host:1616

3. Comece jconsoleno seu computador

jconsole localhost:1616

4. Divirta-se!

PS: durante a etapa 2, usando sshe -Lvocê especifica que a porta 1616 no host local (cliente) deve ser encaminhada para o lado remoto. Este é um túnel ssh e ajuda a evitar firewalls ou vários problemas de rede.

Freedev
fonte
1
IMPRESSIONANTE!! Estou tentando há mais de 6 horas para jmx-remote para uma instância ActiveMQ em java8. FINALMENTE ALGO QUE FUNCIONOU !! Obrigado! :)
Rop
Obrigado, como você eu lutei por cerca de um dia também, e depois de tanto trabalho eu apenas pensei: "Devo escrever isso para ASSIM !!"
freedev
2
É realmente uma pena que a Oracle não mencione "com.sun.management.jmxremote.rmi.port", "java.rmi.server.hostname" docs.oracle.com/javase/8/docs/technotes/guides/management/… I acho que esse era o meu problema.
Rop
Porque, AFAIK, esse problema não é sobre JMX, mas como funciona o RMI. Por exemplo, após este caso, tive o mesmo problema com o jmeter, que usa rmi em sua implementação cliente / servidor.
freedev
2
Funciona. Apenas adicionando minha experiência com os túneis: 1) posso usar "localhost" em "-L 1616: localhost: 1616" 2) não posso alterar a porta de origem, ou seja, isso não funcionará: "-L 9999: localhost: 1616"
gargii
19

Provavelmente, você está tendo problemas com um firewall. O 'problema' é que a porta que você especificou não é a única porta usada, ela usa 1 ou talvez até mais 2 portas para RMI, e essas provavelmente estão bloqueadas por um firewall.

Uma das portas extras não será conhecida de antemão se você usar a configuração RMI padrão, então você tem que abrir uma grande variedade de portas - o que pode não divertir o administrador do servidor.

Há uma solução que não requer a abertura de muitas portas, no entanto, eu a fiz funcionar usando os snippets de origem combinados e dicas de

http://forums.sun.com/thread.jspa?threadID=5267091 - o link não funciona mais

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

http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html

É até possível configurar um túnel ssh e ainda fazê-lo funcionar :-)

Simon Groenewolt
fonte
2
Consegui contornar o firewall usando apenas o alias descrito em simplygenius.com/2010/08/jconsole-via-socks-ssh-tunnel.html junto com a configuração -Djava.rmi.server.hostname conforme mencionado em outra resposta aqui.
Damien
Nota para futuros leitores: o link para forums.sun.comestá quebrado
CDspace
1
Nota para futuros leitores: o link para blogs.oracle.comestá quebrado.
Grimlock de
17

Depois de testar meu Google-fu nos últimos dias, finalmente consegui fazer isso funcionar depois de compilar as respostas do Stack Overflow e desta página http://help.boomi.com/atomsphere/GUID-F787998C- 53C8-4662-AA06-8B1D32F9D55B.html .

Repostagem da página Dell Boomi:

To Enable Remote JMX on an Atom

If you want to monitor the status of an Atom, you need to turn on Remote JMX (Java Management Extensions) for the Atom.

Use a text editor to open the <atom_installation_directory>\bin\atom.vmoptions file.

Add the following lines to the file:

-Dcom.sun.management.jmxremote.port=5002
-Dcom.sun.management.jmxremote.rmi.port=5002
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

A única linha que eu não vi nenhuma capa de resposta do Stack Overflow é

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

No meu caso, eu estava tentando recuperar as métricas Kakfa, então simplesmente alterei a opção acima para corresponder ao -Dcom.sun.management.jmxremote.portvalor. Portanto, sem autenticação de qualquer tipo, a configuração mínima deve ser semelhante a esta:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=(jmx remote port)

-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.rmi.port=(jmx remote port)
-Djava.rmi.server.hostname=(CNAME|IP Address)
Sergio
fonte
1
Mais um para "Google-fu"
kevinarpe
"com.sun.management.jmxremote.rmi.port" era a chave para mim também. Veja também esta resposta: stackoverflow.com/a/22306586/123205
David
Eu não precisava de "com.sun.management.jmxremote.local.only", então não acho que sua configuração seja realmente "mínima"
David
7

As etapas 4 a 7 de Sushicutta podem ser ignoradas adicionando a seguinte linha à etapa 3:

-Dcom.sun.management.jmxremote.rmi.port=<same port as jmx-remote-port>

por exemplo, adicionar parâmetros de inicialização:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=12345
-Dcom.sun.management.jmxremote.rmi.port=12345
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.local.only=false
-Djava.rmi.server.hostname=localhost

Para o encaminhamento de porta, conecte-se usando:

ssh -L 12345:localhost:12345 <username>@<host>

se o seu host for um degrau, simplesmente encadeie a porta executando o seguinte na degrau após o anterior:

ssh -L 12345:localhost:12345 <username>@<host2>

Lembre-se de que hostname = localhost é necessário para garantir que o jmxremote esteja informando a conexão rmi para usar o túnel. Caso contrário, ele pode tentar se conectar diretamente e atingir o firewall.

user2412906
fonte
Este método me ajuda: (1) adiciono parâmetros JMX perdidos e reinicio o aplicativo (2) Em seguida, executo ssh -L <JMX_port>:localhost:<JMX_port> <remote_user>@<remote_host> na máquina local (3) Em seguida, eu me conecto ao JMX remoto usando: jconsole <remote_host>:<JMX_port>
Rib47
6

PROTIP:

As portas RMI são abertas em portnrs arbitrários. Se você tiver um firewall e não quiser abrir as portas 1024-65535 (ou usar vpn), faça o seguinte.

Você precisa consertar (como se tivesse um número conhecido) o registro RMI e as portas do servidor JMX / RMI. Você faz isso colocando um arquivo jar (catalina-jmx-remote.jar está no extra) no lib-dir e configurando um ouvinte especial no servidor:

<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener"
      rmiRegistryPortPlatform="10001" rmiServerPortPlatform="10002" />

(E, claro, os sinalizadores usuais para ativar JMX

    -Dcom.sun.management.jmxremote  \
    -Dcom.sun.management.jmxremote.ssl=false \
    -Dcom.sun.management.jmxremote.authenticate=false \
    -Djava.rmi.server.hostname=<HOSTNAME> \

Consulte: JMX Remote Lifecycle Listener em http://tomcat.apache.org/tomcat-6.0-doc/config/listeners.html

Então você pode se conectar usando este URL horrível:

service:jmx:rmi://<hostname>:10002/jndi/rmi://<hostname>:10001/jmxrmi
supdog
fonte
Tentei o acima c / o jar de extras, e posso ver as portas RMI ouvindo conforme especificado, mas portas aleatórias ainda usadas pelo RMI após conectar-se à porta JVM com VisualVM. Solução alternativa: observe as portas com 'lsof -i' e abra aquelas com conexões bloqueadas.
Joseph Lust
5

Verifique se o seu servidor está protegido por firewall. JMX é baseado em RMI, que abre duas portas quando é iniciado. Uma é a porta de registro, o padrão é 1099 e pode ser especificada pela com.sun.management.jmxremote.portopção. O outro é para comunicação de dados, e é aleatório, o que causa o problema. Uma boa notícia é que, a partir do JDK6, essa porta aleatória pode ser especificada pela com.sun.management.jmxremote.rmi.portopção.

export CATALINA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8991 -Dcom.sun.management.jmxremote.rmi.port=8991 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"
Arganzheng
fonte
4

Obter JMX por meio do Firewall é muito difícil. O problema é que o RMI padrão usa uma segunda porta atribuída aleatoriamente (ao lado do registro RMI).

Temos três soluções que funcionam, mas cada caso precisa de uma diferente:

  1. JMX sobre túnel SSH com proxy Socks, usa RMI padrão com magia SSH http://simplygenius.com/2010/08/jconsole-via-socks-ssh-tunnel.html

  2. JMX MP (alternativa ao RMI padrão), usa apenas uma porta fixa, mas precisa de um jar especial no servidor e no cliente http://meteatamel.wordpress.com/2012/02/13/jmx-rmi-vs-jmxmp/

  3. Inicie o código de formulário do servidor JMX, lá é possível usar RMI padrão e usar uma segunda porta fixa: https://issues.apache.org/bugzilla/show_bug.cgi?id=39055

user85155
fonte
Todas as outras respostas devem ser adicionadas a esta
ruruskyi
2

Ao testar / depurar / diagnosticar problemas JMX remotos , primeiro sempre tente se conectar no mesmo host que contém o MBeanServer (ou seja, localhost), para descartar a rede e outros problemas específicos não JMX.

eljenso
fonte
2

Já existem algumas respostas excelentes aqui, mas existe uma abordagem um pouco mais simples que acho que vale a pena compartilhar.

A abordagem do sushicutta é boa, mas é muito manual, pois você precisa obter a porta RMI todas as vezes. Felizmente, podemos contornar isso usando um proxy SOCKS em vez de abrir explicitamente os túneis de porta. A desvantagem desta abordagem é que o aplicativo JMX que você executa em sua máquina precisa ser configurado para usar um proxy. Na maioria dos processos, você pode fazer isso adicionando propriedades java, mas alguns aplicativos não oferecem suporte para isso.

Passos:

  1. Adicione as opções JMX ao script de inicialização para seu serviço Java remoto:

    -Dcom.sun.management.jmxremote=true
    -Dcom.sun.management.jmxremote.port=8090
    -Dcom.sun.management.jmxremote.ssl=false
    -Dcom.sun.management.jmxremote.authenticate=false
    
  2. Configure uma conexão proxy SOCKS para sua máquina remota:

    ssh -D 9696 [email protected]
    
  3. Configure seu aplicativo de monitoramento Java local para usar o proxy SOCKS (localhost: 9696). Observação: às vezes você pode fazer isso na linha de comando, ou seja:

    jconsole -J-DsocksProxyHost=localhost -J-DsocksProxyPort=9696
    
RichS
fonte
2

O seguinte funcionou para mim (embora eu ache que a porta 2101 realmente não contribuiu para isso):

-Dcom.sun.management.jmxremote.port=2100
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.rmi.port=2101
-Djava.rmi.server.hostname=<IP_ADDRESS>OR<HOSTNAME>

Estou me conectando de uma máquina remota a um servidor que tem o Docker em execução e o processo está dentro do contêiner. Além disso, parei o firewallD, mas não acho que esse seja o problema, pois eu poderia telnet para 2100 mesmo com o firewall aberto. Espero que ajude.

E eu sou.
fonte
1

Estou executando o JConsole / JVisualVm no Windows conectando-se ao Tomcat executando o Linux Redhat ES3.

Desativar a filtragem de pacotes usando o seguinte comando funcionou para mim:

/usr/sbin/iptables -I INPUT -s jconsole-host -p tcp --destination-port jmxremote-port -j ACCEPT

em que jconsole-host é o nome do host ou o endereço do host no qual o JConsole é executado e jmxremote-port é o número da porta definido para com.sun.management.jmxremote.port para gerenciamento remoto.

Kishore
fonte
2
não funcionou para mim em uma instância SUSE Amazon EC2. Acho que o problema está em outro lugar.
djangofan
1

Estou usando o boot2docker para executar contêineres do docker com o Tomcat interno e estou com o mesmo problema, a solução era:

  • Adicionar -Djava.rmi.server.hostname=192.168.59.103
  • Utilizar a mesma porta JMX no hospedeiro e janela de encaixe recipiente, por exemplo: docker run ... -p 9999:9999 .... Usar portas diferentes não funciona.
pequeno
fonte
0

Você também precisa se certificar de que o nome da máquina seja resolvido para o IP ao qual o JMX está vinculado; NÃO localhost nem 127.0.0.1. Para mim, ajudou a colocar uma entrada em hosts que define isso explicitamente.

Joseph
fonte
0

Fazer o JMX passar pelo firewall não é tão difícil. Existe um pequeno problema. Você deve encaminhar ambas as portas configuradas JMX, ou seja. 9010 e uma das portas dinâmicas que escuta na minha máquina era> 30000

Lukasz
fonte
0

Estas são as etapas que funcionaram para mim (debian atrás do firewall no lado do servidor, acessado por VPN do meu Mac local):

verificar ip do servidor

hostname -i

usar parâmetros JVM:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=[jmx port]
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=[server ip from step 1]

executar aplicativo

encontrar pid do processo java em execução

verifique todas as portas usadas por JMX / RMI

netstat -lp | grep [pid from step 4]

abra todas as portas da etapa 5 no firewall

Voila.

Mariusz
fonte
0

Para dar uma contribuição, foi o que fiz no CentOS 6.4 para Tomcat 6.

  1. Desligar serviço iptables

    service iptables stop
    
  2. Adicione a seguinte linha a tomcat6.conf

    CATALINA_OPTS="${CATALINA_OPTS} -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8085 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=[host_ip]"
    

Desta forma, consegui me conectar de outro PC usando JConsole.

Endereço.
fonte
0

Estou tentando JMC para executar o Flight Recorder (JFR) para o perfil NiFi em um servidor remoto que não oferece um ambiente gráfico no qual executar o JMC.

Com base nas outras respostas fornecidas aqui, e após muitas tentativas e erros, aqui está o que estou fornecendo para a JVM ( conf / bootstrap.conf ) quando inicio o NiFi:

java.arg.90=-Dcom.sun.management.jmxremote=true
java.arg.91=-Dcom.sun.management.jmxremote.port=9098
java.arg.92=-Dcom.sun.management.jmxremote.rmi.port=9098
java.arg.93=-Dcom.sun.management.jmxremote.authenticate=false
java.arg.94=-Dcom.sun.management.jmxremote.ssl=false
java.arg.95=-Dcom.sun.management.jmxremote.local.only=false
java.arg.96=-Djava.rmi.server.hostname=10.10.10.92  (the IP address of my server running NiFi)

Coloquei isso em / etc / hosts , embora duvide que seja necessário:

10.10.10.92   localhost

Então, ao iniciar o JMC, crio uma conexão remota com estas propriedades:

Host: 10.10.10.92
Port: 9098
User: (nothing)
Password: (ibid)

A propósito, se eu clicar no URL do serviço JMX personalizado, vejo:

service:jmx:rmi:///jndi/rmi://10.10.10.92:9098/jmxrmi

Isso finalmente funcionou por mim.

Russ Bateman
fonte