Почему Java открывает 3 порта при настройке JMX?
Я запускаю свою программу Java с помощью JDK7 на Centos6. Я включаю JMX, используя следующие параметры:
JAVA_OPTS="${JAVA_OPTS} -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9123 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=true"
Когда я проверяю, какие порты открыты, я обнаруживаю 2 дополнительных случайных порта:
netstat -plunt | grep java
tcp 0 0 :::9123 :::* LISTEN 13295/java
tcp 0 0 :::59927 :::* LISTEN 13295/java
tcp 0 0 :::59928 :::* LISTEN 13295/java
Обратите внимание, что каждый перезапуск только сконфигурированный порт 9123 остается таким же, а два дополнительных порта меняют значения.
netstat -plunt | grep java
tcp 0 0 :::9123 :::* LISTEN 13331/java
tcp 0 0 :::59932 :::* LISTEN 13331/java
tcp 0 0 :::59933 :::* LISTEN 13331/java
Что такое 2 дополнительных порта и почему они открыты?
Как настроить 2 дополнительных случайных порта?
Как настроить ::ffff:127.0.0.1
будет отображаться перед всеми портами, открытыми JMX?
Почему один порт не используется при подключении к JConsole?
Добавлен пояснение ответа
К сожалению, дополнительный случайный порт все еще открыт
Чтобы напомнить вам, я использую Centos 6.
Мои настройки Tomcat выглядят так (Tomcat не развертывает приложения):
CATALINA_OPTS="${CATALINA_OPTS} -XX:+DisableAttachMechanism -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=true -Djava.rmi.server.useLocalHostname=true -Djava.rmi.server.useCodebaseOnly=true -Dcom.sun.management.jmxremote.port=9123 -Dcom.sun.management.jmxremote.rmi.port=9123"
Процесс Tomcat выглядит следующим образом:
/usr/java/jdk1.7.0_51/bin/java -Djava.util.logging.config.file=/usr/tomcat-7.0.47/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -XX:+DisableAttachMechanism -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=true -Djava.rmi.server.useLocalHostname=true -Djava.rmi.server.useCodebaseOnly=true -Dcom.sun.management.jmxremote.port=9123 -Dcom.sun.management.jmxremote.rmi.port=9123 -Djava.endorsed.dirs=/usr/tomcat-7.0.47/endorsed -classpath /usr/tomcat-7.0.47/bin/bootstrap.jar:/usr/tomcat-7.0.47/bin/tomcat-juli.jar -Dcatalina.base=/usr/tomcat-7.0.47 -Dcatalina.home=/usr/tomcat-7.0.47 -Djava.io.tmpdir=/usr/tomcat-7.0.47/temp org.apache.catalina.startup.Bootstrap start
К сожалению, каждый раз, когда я вижу дополнительный порт прослушивания:
tcp 0 0 :::38830 :::* LISTEN 790/java
tcp 0 0 ::ffff:127.0.0.1:8080 :::* LISTEN 790/java
tcp 0 0 :::9123 :::* LISTEN 790/java
Дополнительный запуск:
tcp 0 0 ::ffff:127.0.0.1:8080 :::* LISTEN 2348/java
tcp 0 0 :::36252 :::* LISTEN 2348/java
tcp 0 0 :::9123 :::* LISTEN 2348/java
Кстати, почему я не вижу ::ffff:127.0.0.1
перед портами RMI?
Добавлен второй раз, чтобы прояснить комментарий
Это не связано с Tomcat. Я попытался запустить ant с аналогичными настройками:
Процесс Ant выглядит следующим образом:
/usr/bin/java -XX:+DisableAttachMechanism -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=true -Djava.rmi.server.useLocalHostname=true -Djava.rmi.server.useCodebaseOnly=true -Dcom.sun.management.jmxremote.port=9123 -Dcom.sun.management.jmxremote.rmi.port=9123 -classpath /usr/apache-ant-1.9.2/lib/ant-launcher.jar -Dant.home=/usr/apache-ant-1.9.2 -Dant.library.dir=/usr/apache-ant-1.9.2/lib org.apache.tools.ant.launch.Launcher -cp sleep
К сожалению, каждый раз, когда я вижу дополнительный порт прослушивания:
tcp 0 0 :::41200 :::* LISTEN 13597/java
tcp 0 0 :::9123 :::* LISTEN 13597/java
Дополнительный запуск:
tcp 0 0 :::58356 :::* LISTEN 13629/java
tcp 0 0 :::9123 :::* LISTEN 13629/java
Ответ: Это ошибка Java
Я успешно открыл ошибку на Java:
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8035404
Ответы
Ответ 1
Вопреки распространенному мнению, JMX/RMI не должен открывать все эти порты. Фактически вы можете заставить их быть одинаковыми, что будет означать, что в конце дня вам нужно будет только пробить одно отверстие в брандмауэре (если брандмауэр вас беспокоит).
Попробуйте установить Свойства системы:
com.sun.management.jmxremote.port
com.sun.management.jmxremote.rmi.port
к тому же значению!!
Явная установка этих параметров остановит RMI от выбора случайных портов. Установив их на одно и то же значение, убедитесь, что он открывает меньше портов для прослушивания.
Это будет работать в обновлении версии Java 7 25 или более поздней версии.
Что такое третий порт?
Третий порт, который вы видите, открываемым вашим приложением (или вторым, если вы следовали моему совету выше), используется API-интерфейсом Java Attach. Это то, что использует JConsole для подключения к "Local Process". Функция API Java Attach API включена по умолчанию с Java 6 независимо от свойства com.sun.management.jmxremote
. Эта функция будет использовать случайный порт, но это действительно не имеет значения, поскольку функция позволяет только соединения с самим хостом. Если вам действительно не нравится эта функция, вы можете добавить -XX:+DisableAttachMechanism
в командную строку, чтобы отключить функцию Java Attach API. Тогда вы больше не увидите, как Java-процесс (в данном случае Tomcat) прослушивает случайный порт.
Как заставить JMX прослушивать только интерфейс loopback
С помощью пользовательского приложения вы должны использовать RMIServerSocketFactory, но это Tomcat, поэтому вам придется делать это с помощью Tomcat JMX Remote Lifecycle Listener.
С другой стороны, теперь не имеет значения, что у вас есть свойство com.sun.management.jmxremote.local.only
, так как Java 7. Он гарантирует, что разрешены только соединения с самого хоста. Имейте в виду, что эта библиотека JMX не достигает этого путем привязки к интерфейсу loopback, который, безусловно, был бы одним из способов сделать это, но также и незначительным неточным, поскольку у хоста может быть несколько интерфейсов loopback.
На самом деле, по большому счету (с последними дополнениями к JDK wrt JMX), я бы сказал, что Tomcat JMX Remote Lifecycle Listener теперь избыточен, за исключением случаев, когда вы хотите привязываться к действительно нечетному сетевому интерфейсу.
Ответ 2
Поскольку jmx инкапсулирован в rmi, который очень брандмауэром и nat недружелюбен. Избегайте его, если можете, есть альтернативная инкапсуляция, называемая jmxmp.
Посмотрите, что может вам помочь:
http://blog.markfeeney.com/2010/10/jmx-through-ssh-tunnel.html
http://jrds.fr/sourcetype/jmx/start#jmx_protocols
Ответ 3
В соответствии с проблемой, которую Майкл открыл, это кажется ожидаемым поведением https://bugs.openjdk.java.net/browse/JDK-8035404