Удаленное соединение JMX
Я пытаюсь открыть соединение JMX с Java-приложением, запущенным на удаленной машине.
JVM приложения настроена со следующими параметрами:
- com.sun.management.jmxremote
- com.sun.management.jmxremote.port = +1088
- com.sun.management.jmxremote.authenticate = ложь
- com.sun.management.jmxremote.ssl= ложь
Я могу подключиться с помощью localhost:1088
используя jconsole или jvisualvm. Но я не могу подключиться с помощью xxx.xxx.xxx.xxx:1088
с удаленной машины.
Между серверами или операционной системой нет брандмауэра. Но чтобы устранить эту возможность я telnet xxx.xxx.xxx.xxx 1088
и я думаю, что он подключается, так как экран консоли становится пустым.
Оба сервера являются Windows Server 2008 x64. Пробовал с 64-битной JVM и 32-битной, ни одна не работает.
11 ответов
Если бы это было в Linux, проблема заключалась бы в том, что localhost - это петлевой интерфейс, вам нужно приложение для привязки к вашему сетевому интерфейсу.
Вы можете использовать netstat для подтверждения того, что он не связан с ожидаемым сетевым интерфейсом.
Вы можете сделать эту работу, вызвав программу с системным параметром java.rmi.server.hostname="YOUR_IP"
либо в качестве переменной среды, либо с использованием
java -Djava.rmi.server.hostname=YOUR_IP YOUR_APP
Я потратил больше одного дня, пытаясь заставить JMX работать за пределами localhost. Похоже, что SUN/Oracle не смогли предоставить хорошую документацию по этому вопросу.
Убедитесь, что следующая команда возвращает вам реальный IP-адрес или имя хоста. Если он возвращает что-то вроде 127.0.0.1, 127.0.1.1 или localhost, он не будет работать, и вам придется обновить /etc/hosts
файл.
hostname -i
Вот команда, необходимая для включения JMX даже извне
-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
Где, как вы и предполагали, myserver.example.com должен соответствовать тому, что hostname -i
возвращается.
Очевидно, вы должны быть уверены, что брандмауэр не блокирует вас, но я почти уверен, что это не ваша проблема, проблема в том, что последний параметр не задокументирован.
В моем тестировании с Tomcat и Java 8 JVM открывала эфемерный порт в дополнение к порту, указанному для JMX. Следующий код исправил меня; Попробуйте, если у вас возникли проблемы, когда ваш клиент JMX (например, VisualVM не подключается).
-Dcom.sun.management.jmxremote.port=8989
-Dcom.sun.management.jmxremote.rmi.port=8989
http://blogs.oracle.com/jmxetc/entry/troubleshooting_connection_problems_in_jconsole
Если вы пытаетесь получить доступ к серверу, который находится за NAT - вам, скорее всего, придется запустить сервер с опцией
-Djava.rmi.server.hostname=<public/NAT address>
так что заглушки RMI, отправленные клиенту, содержат публичный адрес сервера, позволяющий клиенту получать к нему доступ извне.
Кажется, что ваша окончательная цитата приходит слишком рано. Это должно быть после последнего параметра.
Этот трюк сработал для меня.
Я заметил кое-что интересное: когда я запускаю свое приложение, используя следующую командную строку:
java -Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
Если я пытаюсь подключиться к этому порту с удаленного компьютера с помощью jconsole, TCP-соединение завершается успешно, некоторые данные обмениваются между удаленным jconsole и локальным агентом jmx, где развернут мой MBean, а затем jconsole отображает сообщение об ошибке подключения. Я выполнил захват Wireshark, и он показывает обмен данными от агента и jconsole.
Таким образом, это не проблема сети, если я выполняю netstat -an с или без системного свойства java.rmi.server.hostname, у меня есть следующие привязки:
TCP 0.0.0.0:9999 0.0.0.0:0 LISTENING
TCP [::]:9999 [::]:0 LISTENING
Это означает, что в обоих случаях сокет, созданный на порту 9999, принимает подключения с любого хоста по любому адресу.
Я думаю, что содержимое этого системного свойства используется где-то при соединении и сравнивается с фактическим IP-адресом, используемым агентом для связи с jconsole. И если эти адреса не совпадают, соединение не устанавливается.
У меня не было этой проблемы при подключении с того же хоста с помощью jconsole, только с реальных физических удаленных хостов. Итак, я полагаю, что эта проверка выполняется только тогда, когда соединение приходит извне.
Единственное, что мне помогло, - это установить /etc/hosts, чтобы он указывал имя хоста на ip, а не на интерфейс обратной связи, а затем перезапускал мое приложение.
кошка /etc/hosts
127.0.0.1 localhost.localdomain localhost
192.168.0.1 myservername
Это моя конфигурация:
-Dcom.sun.management.jmxremote.port=1617
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
Большое спасибо, это работает так:
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
Попробуйте это, я тестировал доступ к JMX внутри контейнера докеров
-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
затем
Локальный хост $ jconsole:16000
Я знаю, что эта ветка довольно старая, но есть дополнительная опция, которая очень поможет. Смотрите здесь: https://realjenius.com/2012/11/21/java7-jmx-tunneling-freedom/
-Dcom.sun.management.jmxremote.rmi.port=1099
Чтобы включить JMX remote, передайте ниже параметры VM вместе с 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
У меня та же проблема, и я изменяю любое имя хоста, которое совпадает с именем локального хоста, на 0.0.0.0, после этого оно работает.