Подтвердить что ты не робот

Как подключиться к экземплярам Java, работающим на EC2, используя JMX

У нас возникла проблема подключения к нашим Java-приложениям, работающим в кластере Amazon EC2. Мы определенно допустили как "порт JMX" (который обычно является портом реестра RMI), так и порт сервера (который выполняет большую часть работы) для группы безопасности для рассматриваемых экземпляров. Jconsole подключается, но, кажется, висит и никогда не показывает никакой информации.

Мы запускаем нашу java с чем-то вроде следующего:

java -server -jar foo.jar other parameters here > java.log 2>&1

Мы попытались:

  • Telnets для подключения портов, но информация не отображается.
  • Мы можем запустить jconsole в самом экземпляре, используя remote-X11 поверх ssh, и он соединяет и показывает информацию. Таким образом, JRE экспортирует его локально.
  • Открытие всех портов в группе безопасности. Weeee.
  • Использование tcpdump, чтобы убедиться, что трафик не идет на другие порты.
  • Имитация локально. Мы всегда можем подключаться к нашим локальным JRE или тем, которые работают в другом месте в нашей сети, используя те же параметры приложения.

java -version выходы:

OpenJDK Runtime Environment (IcedTea6 1.11.5) (amazon-53.1.11.5.47.amzn1-x86_64)
OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode)

В качестве альтернативы мы используем мой Simple JMX, который позволяет нам устанавливать как реестр RMI, так и серверные порты, которые, как правило, случайно выбранный реестром RMI. Вы также можете сделать это с помощью следующего JMX URI:

service:jmx:rmi://localhost:" + serverPort + "/jndi/rmi://:" + registryPort + "/jmxrmi"

В настоящее время мы используем один и тот же порт для сервера и реестра. Раньше мы использовали X как реестр-порт и X+1 для сервера-порта, чтобы упростить правила группы безопасности. Вы подключаетесь к реестровому порту в jconsole или другом клиенте JMX, который вы используете.

4b9b3361

Ответ 1

У нас возникла проблема подключения к нашим Java-приложениям, работающим в кластере Amazon EC2.

Оказывается, проблема была комбинацией двух отсутствующих настроек. Первое заставляет JRE предпочесть ipv4, а не v6. Это было необходимо (я думаю), поскольку мы пытаемся подключиться к нему через адрес v4:

-Djava.net.preferIPv4Stack=true

Реальным блокировщиком был тот факт, что JMX работает, сначала связавшись с портом RMI, который отвечает именем хоста и портом для подключения JMX-клиента. Без дополнительных настроек он будет использовать локальный IP-адрес окна, который является 10.X.X.X виртуальным адресом, к которому удаленный клиент не может перейти. Нам нужно было добавить следующий параметр, который является внешним именем хоста или IP-адресом сервера - в этом случае он является упругим именем сервера.

-Djava.rmi.server.hostname=ec2-107-X-X-X.compute-1.amazonaws.com

Трюк, если вы пытаетесь автоматизировать свои экземпляры EC2 (и почему, черт возьми, не хотите), как найти этот адрес во время выполнения. Для этого вам нужно добавить в наше приложение что-то вроде следующего: script:

# get our _external_ hostname
RMI_HOST=`wget -q -O - http://169.254.169.254/latest/meta-data/public-hostname`
...
java -server \
    -Djava.net.preferIPv4Stack=true -Djava.rmi.server.hostname=$RMI_HOST \
    -jar foo.jar other parameters here > java.log 2>&1

Таинственный 169.254.169.254 IP в команде wget выше предоставляет информацию о том, что экземпляр EC2 может запросить о себе. Я разочарован тем, что это не включает теги, которые доступны только при аутентифицированном вызове.

Сначала я использовал адрес extern ipv4, но похоже, что JDK пытается подключиться к серверному порту, когда он запускается. Если он использует внешний IP-адрес, это замедляет время загрузки приложения до истечения этого времени. Имя общедоступного узла разрешается локально для адреса 10-net и для public-ipv4 извне. Таким образом, приложение теперь работает быстро, и клиенты JMX все еще работают. Woo hoo!

Надеюсь, это поможет кому-то другому. Стоимость мне сегодня 3 часа.

Чтобы заставить JMX-сервер запускать сервер и реестр RMI на определенных портах, чтобы вы могли заблокировать их в группах безопасности EC2, см. этот ответ:

Как закрыть rmiregistry, запущенный на определенном порту?

Edit:

У нас только что эта проблема повторилась. Кажется, что Java JMX-код выполняет поиск по имени хоста по имени хоста и использует их, чтобы попытаться подключиться и проверить соединение JMX.

Проблема заключается в том, что локальное имя хоста для этого поля должно быть разрешено для локального ip-поля. Например, если ваш /etc/sysconfig/network имеет HOSTNAME=server1.foobar.com, то если вы выполняете поиск DNS на server1.foobar.com, вы должны перейти к виртуальному адресу 10-NET. Мы создали собственный /etc/hosts файл и имя хоста локального хоста отсутствовало в файле. Это заставило наши приложения либо приостанавливаться при запуске, либо вообще не запускаться.

Наконец

Одним из способов упрощения создания JMX является использование пакета SimpleJMX.

Ответ 2

За второй ответ Почему соединение JMX с Amazon EC2 не удается?, сложность здесь заключается в том, что по умолчанию порт RMI выбирается произвольно, а клиентам нужен доступ как для портов JMX, так и для RMI. Если вы используете jdk7u4 или более позднюю версию, порт RMI можно указать через свойство приложения. Запуск моего сервера со следующими настройками JMX работал у меня:

Без аутентификации:

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=9999 
-Dcom.sun.management.jmxremote.rmi.port=9998 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.authenticate=false 
-Djava.rmi.server.hostname=<public EC2 hostname>

С проверкой подлинности:

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=9999 
-Dcom.sun.management.jmxremote.rmi.port=9998 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.authenticate=true 
-Dcom.sun.management.jmxremote.password.file=/path/to/jmxremote.password
-Djava.rmi.server.hostname=<public EC2 hostname>

Я также открыл порты 9998-9999 в группе безопасности EC2 для моего экземпляра.

Ответ 3

Ответ, данный Gray, работал у меня, однако я обнаружил, что мне нужно открывать порты TCP от 0 до 65535, или я не могу войти. Я думаю, что вы можете подключиться к основному порту JMX, а затем получить еще один назначены. Я получил от этот пост в блоге, который всегда работал хорошо для меня.

Ответ 4

Немного другой подход с использованием туннелей ssh ​​

  • Передайте следующие флагов в JVM

-Dcom.sun.management.jmxremote.port=1099 -Djava.net.preferIPv4Stack=true -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=127.0.0.1

  1. Проверьте, какие порты java начали использовать

netstat -tulpn | grep java

tcp 0 0 0.0.0.0:37484 0.0.0.0:* LISTEN 2904/java tcp 0 0 0.0.0.0:1099 0.0.0.0:* LISTEN 2904/java tcp 0 0 0.0.0.0:45828 0.0.0.0:* LISTEN 2904/java

  1. Сделать ssh туннелями для всех портов

ssh -N -L 1099:127.0.0.1:1099 [email protected]<ec2_ip> ssh -N -L 37484:127.0.0.1:37484 [email protected]<ec2_ip> ssh -N -L 45828:127.0.0.1:45828 [email protected]<ec2_ip>

  1. Подключение с помощью Java Mission Control к "localhost: 1099"