Java AmazonのEC2クラスターで実行されているアプリケーションに接続できません。「JMXポート」(通常はRMIレジストリポート)の両方を許可していますおよび問題のインスタンスのセキュリティグループへのサーバーポート(ほとんどの作業を行います)。Jconsoleは接続しているように見えますが、ハングして情報が表示されません。
Javaを次のように実行しています。
Java -server -jar foo.jar other parameters here > Java.log 2>&1
私たちは試しました:
jconsole
を実行すると、接続して情報が表示されます。したがって、JREはローカルにエクスポートしています。tcpdump
を使用して、トラフィックが他のポートに送信されないようにします。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クライアントに接続します。
AmazonのEC2クラスターで実行されているJavaアプリケーションへの接続に問題があります。
問題は2つの不足している設定の組み合わせであることがわかります。 1つ目は、JREがipv4を優先し、v6を優先しないことを強制します。これは(おそらく)v4アドレスを介して接続しようとしているため必要でした。
-Djava.net.preferIPv4Stack=true
実際のブロッカーは、JMXクライアントが接続するhostnameとポートで応答するRMIポートに最初に接続することによってJMXが機能するという事実でした。追加の設定なしで、リモートクライアントがルーティングできない10.X.X.X
仮想アドレスであるボックスのローカルIPを使用します。サーバーのexternalホスト名またはIPである次の設定を追加する必要がありました。この場合、サーバーのエラスティックホスト名です。
-Djava.rmi.server.hostname=ec2-107-X-X-X.compute-1.amazonaws.com
EC2インスタンスを自動化しようとしている場合(そして、なぜそうしないのか)の秘訣は、実行時にこのアドレスを見つける方法です。これを行うには、アプリケーションのブートスクリプトに次のようなものを追加する必要があります。
# 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
上記のwget
コマンドの不可解な169.254.169.254
IPは、EC2インスタンスがそれ自体について要求できる情報を提供します。これには、認証済みの呼び出しでのみ使用可能なタグが含まれていないことに失望しています。
最初はextern ipv4アドレスを使用していましたが、起動時にJDKがサーバーポートへの接続を試みているようです。外部IPを使用している場合は、タイムアウトになるまでアプリケーションの起動時間が遅くなっていました。 public-hostnameはローカルで10ネットアドレスに解決され、外部でpublic-ipv4に解決されます。したがって、アプリケーションは高速で起動し、JMXクライアントは引き続き機能します。ウフー!
これが他の誰かを助けることを願っています。今日は3時間かかります。
JMXサーバーに強制的にサーバーおよびを指定したポートで起動して、EC2セキュリティグループでそれらをブロックできるようにするには、次の回答を参照してください。
編集:
この問題が再発しました。 Java JMXコードは、ボックスのホスト名に対していくつかのホスト名ルックアップを行っており、それらを使用してJMX接続の接続と確認を試みているようです。
この問題は、ボックスのローカルホスト名をボックスのローカルIPに解決する必要があるという要件のようです。たとえば、/etc/sysconfig/network
にHOSTNAME=server1.foobar.com
がある場合、server1.foobar.com
でDNSルックアップを実行すると、10-NET仮想アドレスに到達するはずです。独自の/etc/hosts
ファイルを生成していましたが、ローカルホストのホスト名がファイルにありませんでした。これにより、アプリケーションが起動時に一時停止するか、まったく起動しなくなりました。
最後に
JMXの作成を単純化する1つの方法は、my SimpleJMXパッケージ を使用することです。
2番目の回答ごと Amazon EC2へのJMX接続が失敗する理由 、ここでの問題は、デフォルトで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>
また、インスタンスのEC2セキュリティグループでポート9998〜9999を開きました。
SSHトンネルを使用した少し異なるアプローチ
-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
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
ssh -N -L 1099:127.0.0.1:1099 ubuntu@<ec2_ip> ssh -N -L 37484:127.0.0.1:37484 ubuntu@<ec2_ip> ssh -N -L 45828:127.0.0.1:45828 ubuntu@<ec2_ip>
グレイの答えがうまくいきましたが、TCPポート0から65535まで開く必要があるか、入りません。私はと思いますメインのJMXポートに接続してから、別のポートを割り当てることができます このブログの投稿 から取得しました。