31

AmazonのEC2クラスターで実行されているJavaアプリケーションへの接続に問題があります。問題のインスタンスのセキュリティグループには、「JMXポート」(通常はRMIレジストリポート)サーバーポート(ほとんどの作業を行う)の両方を確実に許可しています。Jconsoleは接続しますが、ハングしているようで、情報が表示されません。

次のようなJavaを実行しています。

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

私たちは試しました:

  • ポートへのTelnetは接続されますが、情報は表示されません。
  • jconsolessh経由でremote-X11を使用してインスタンス自体で実行でき、接続して情報を表示します。したがって、JREそれをローカルにエクスポートしています。
  • セキュリティグループ内のすべてのポートを開きます。うわぁ。
  • tcpdumpトラフィックが他のポートに送信されないようにするために使用します。
  • ローカルでシミュレートします。同じアプリケーションパラメータを使用して、ローカルJREまたはネットワーク上の他の場所で実行されている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レジストリによって半ランダムに選択されるサーバーポートの両方を設定できます。次のJMXURIのようなものでこれを強制することもできます。

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

最近では、サーバーとレジストリの両方に同じポートを使用しています。これまで、セキュリティグループのルールを簡単にするためにX、レジストリポートおよびサーバーポートとして使用していました。X+1レジストリポートjconsoleまたは使用しているJMXクライアントに接続します。

4

5 に答える 5

43

AmazonのEC2クラスターで実行されているJavaアプリケーションへの接続に問題があります。

問題は、2つの欠落している設定の組み合わせであることが判明しました。1つ目は、JREがv6ではなくipv4を優先するように強制します。これは、v4アドレスを介して接続しようとしているため(おそらく)必要でした。

-Djava.net.preferIPv4Stack=true

本当のブロッカーは、JMXクライアントが接続するためのホスト名とポートで応答するRMIポートに最初に接続することによってJMXが機能するという事実でした。10.X.X.X追加の設定がない場合、リモートクライアントがルーティングできない仮想アドレスであるボックスのローカルIPが使用されます。サーバーの外部ホスト名または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

上記のコマンドの不思議な169.254.169.254IPはwget、EC2インスタンスがそれ自体について要求できる情報を提供します。認証された通話でのみ使用できるタグが含まれていないことに失望しています。

最初はexternipv4アドレスを使用していましたが、JDKが起動時にサーバーポートに接続しようとしているようです。外部IPを使用している場合、タイムアウトになるまでアプリケーションの起動時間が遅くなります。public-hostnameは、ローカルで10-netアドレスに解決され、外部でpublic-ipv4に解決されます。そのため、アプリケーションは高速で起動し、JMXクライアントは引き続き機能します。ウーフー!

これが他の誰かに役立つことを願っています。今日は3時間かかりました。

JMXサーバーに指定されたポートでサーバーRMIレジストリを強制的に起動させ、EC2セキュリティグループでそれらをブロックできるようにするには、次の回答を参照してください。

特定のポートで実行されているrmiregistryを閉じる方法は?

編集:

この問題が再発しました。Java JMXコードは、ボックスのホスト名に対していくつかのホスト名ルックアップを実行し、それらを使用してJMX接続の接続と検証を試みているようです。

この問題は、ボックスのローカルホスト名がボックスのlocal-ipに解決される必要があるという要件のようです。たとえば、を/etc/sysconfig/network持っているHOSTNAME=server1.foobar.com場合、でDNSルックアップを実行するserver1.foobar.comと、10-NET仮想アドレスに到達する必要があります。独自の/etc/hostsファイルを生成していましたが、ローカルホストのホスト名がファイルにありませんでした。これにより、アプリケーションが起動時に一時停止するか、まったく起動しなくなりました。

最後に

JMXの作成を簡素化する1つの方法は、SimpleJMXパッケージを使用することです。

于 2012-12-05T23:48:09.787 に答える
18

2 番目の回答によると、Amazon EC2 への JMX 接続が失敗するのはなぜですか? 、ここでの問題は、デフォルトで RMI ポートがランダムに選択され、クライアントが JMX ポートと RMI ポートの両方にアクセスする必要があることです。jdk7u4 以降を実行している場合は、RMI ポートを app プロパティで指定できます。次の 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 を開きました。

于 2014-12-30T07:23:05.467 に答える
7

ssh トンネルを使用した少し異なるアプローチ

  1. (リモート マシン上) 次のフラグを 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
    
  2. (リモート マシンで) 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
    
  3. (ローカル マシンで) すべてのポートの ssh トンネルを作成します。

    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>`
    
  4. (ローカル マシン上) Java Mission Control で接続localhost:1099

于 2017-04-17T20:10:24.080 に答える
1

グレイの答えはうまくいきましたが、TCPポート0〜65535を開く必要があるか、入らないことがわかりました。メインのJMXポートに接続して、別のポートを割り当てることができると思います。私はいつも私のためにうまくいったこのブログ投稿からそれを得ました。

于 2013-03-21T01:46:50.780 に答える