28

私の具体的な質問は、JDK 1.6で使用されているJMXに関係しています。JRE1.6を使用してJavaプロセスを実行している場合、

com.sun.management.jmxremote

コマンドラインで、JavaはリモートJMX接続用のデフォルトポートを選択しますか?

経歴:私は現在、顧客がリモートマシンからJMXを介してプロセスの1つに接続できるようにする手順を開発しようとしています。目標は、リアルタイムディスプレイコンソールで発生する状況のリモートデバッグを容易にすることです。サービスレベルアグリーメントにより、可能な限り多くのデータをキャプチャし、状況が複雑すぎてすぐに修正できない場合は、ディスプレイコンソールを再起動して、サーバー側に再接続できるようにする意欲があります。

コンソールへの物理アクセスがあれば、JDK 1.6プロセスでjconsoleを実行し、 JDK1.6.7以降のプロセスでjvisualvmを実行できることを認識しています。ただし、運用上の要件と人的問題が関係しているため、リモートで必要なデータを取得して、それらを再度稼働させることを強く望んでいます。

編集:コマンドラインポートのプロパティを認識しています

com.sun.management.jmxremote.port=portNum

私が答えようとしている質問は、コマンドラインでそのプロパティを設定しない場合、Javaはリモート監視用に別のポートを選択するのでしょうか?もしそうなら、それが何であるかをどのように判断できますか?

4

7 に答える 7

88

私の知る限り、

以下は、JMX クライアント プロセス( jconsole、jmxterm、mc4j、jvmstat、jmxmonitor、jps などの管理アプリケーション) をJMX サーバー プロセス(エージェント) に接続するための可能性です。

JMX クライアントと JMX サーバーを接続するプロトコルは、「Java RMI」(別名「RMI-JRMP」) であると想定されます。これがデフォルトです。他のプロトコル、特に「RMI-IIOP」と「JMXMP」を構成できます。特別なプロトコルが可能です。たとえば、MX4Jプロジェクトは、SOAP/HTTP および HTTP を介したさまざまなシリアライゼーション プロトコルを追加で提供します。

構成の詳細については、 Sun/Oracle のドキュメントを参照してください。

jre/lib/management/management.propertiesまた、JDK ディストリビューションのファイルも確認してください。

したがって、可能性:

ケース 0: JVM は特定の構成なしで開始されます

Java 6 より前: JVM は JMX サーバーとして動作しません。JVM 内で実行されるプログラムは、プログラムによって JVM のMBeanServerにアクセスし、それを使用してスレッド間の興味深いデータ交換や JVM の監視を行うことができますが、JVM プロセスの外部からの管理はできません。

Java 6 以降: 明示的に構成されていない場合でも、「ケース 1」で説明されているように、ローカルで(同じマシンから) JVM の JMX 機能にアクセスできます。

ケース 1: JVM は以下で開始されます-Dcom.sun.management.jmxremote

JVM は、ローカル(同一マシンのみ) JMX サーバーとして機能するように構成されています。

この場合 (原則として Sun/Oracle JVM のみ)、JMX クライアントは、/tmp/hsperfdata_[user]. これは、Sun のドキュメントで言及されており、「ローカル監視」(およびAttach API ) と呼ばれています。パーミッションを正しく設定できないため、FAT ファイルシステムでは機能しません。このブログエントリを参照してください。

Sunjconsoleは、JMX サーバーとは別のマシンで実行することをお勧めします。JMX サーバーはjconsole明らかにリソースを大量に消費するため、この「ローカル監視」は必ずしも良い考えではありません。

ただし、ローカル監視はかなり安全で、ローカルでのみ使用でき、ファイルシステムのアクセス許可によって簡単に制御できます.

ケース 2: JMX サーバーは以下で開始されます-Dcom.sun.management.jmxremote.port=[rmiregistryport]

JVM は、複数の TCP ポートをリッスンする JMX サーバーとして機能するように構成されています。

コマンド ラインで指定されたポートは JVM によって割り当てられ、そこで RMI レジストリが使用可能になります。レジストリは、「jmxrmi」という名前のコネクタをアドバタイズします。これは、JMX RMI サーバーがリッスンし、実際のデータ交換が行われる、ランダムに割り当てられた 2 番目の TCP ポート (「エフェメラル」ポート) を指します。

「ケース 1」で説明したローカルは、「ケース 2」で常に有効になります。

JMX サーバーはデフォルトですべてのインターフェースをリッスンするため、ローカルで 127.0.0.1:[rmiregistryport] に接続するだけでなく、[任意の外部 IP アドレス]:[一部のポート] にリモートで接続して接続 (および制御) できます。 .

これは、セキュリティへの影響を検討する必要があることを意味します。を設定するだけで、JVM が 127.0.0.1:[rmiregistryport] をリッスンできます-Dcom.sun.management.jmxremote.local.only=true

エフェメラル ポートがどこに割り当てられるかを指定できないのはかなり残念なことです。起動時に常にランダムに選択されます。これは、ファイアーウォールがスイスチーズのようになる必要があることを意味しているのかもしれません! ただし、回避策があります特に、Apache Tomcat は、 JMX Remote Lifecycle Listenerを介してエフェメラル JMX RMI サーバー ポートを設定します。この小さな魔法を実行するコードは、org.apache.catalina.mbeans.JmxRemoteLifecycleListenerにあります。

この方法を使用する場合は、次のことを確認してください。

  1. JMX クライアントは JMX サーバーに対して認証する必要があります
  2. クライアントとサーバー間の TCP 交換は、SSL を使用して暗号化されます。

その方法については、Sun/Oracle のドキュメントに記載されています。

その他のアプローチ

RMI プロトコルを使用する必要がないように、興味深い順列を行うことができます。特に、サーブレット エンジン (Jetty など) をプロセスに追加できます。次に、一部の HTTP ベースの交換を内部的に JVM への直接アクセスに変換するサーブレットを追加しますMBeanServer。その後、「ケース 0」になりますが、おそらく HTML ベースのインターフェイスを介して管理機能を利用できます。JBoss JMX コンソールはこの例です。

このドキュメントに従って、SNMPを直接使用することもできます(私が試したことはありません)。

時間の表示と通知

それでは、コードで JXM 交換を説明します。Sunoracle のチュートリアルから着想を得ています。

これは Unix で動作します。以下を使用して JMX サーバーとして構成された JVM を使用します。

-Dcom.sun.management.jmxremote.port=9001

lsof開いている TCP ポートを確認するために使用します。

lsof -p <processid> -n | grep TCP

次のようなレジストリ ポートとエフェメラル ポートが表示されるはずです。

java    1068 user  127u  IPv6 125614246                 TCP *:36828 (LISTEN)
java    1068 user  130u  IPv6 125614248                 TCP *:9001  (LISTEN)

tcpdumpJMX クライアントと JMX サーバー間のパケット交換を検査するために使用します。

tcpdump -l -XX port 36828 or port 9001

.java.policyクライアントが実際にリモートで接続できるように、ホーム ディレクトリにファイルを設定します。

grant {
    permission java.net.SocketPermission 
    "<JMX server IP address>:1024-65535", "connect,resolve";
};

そして、これを実行して何が起こるか見ることができます:

package rmi;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import javax.management.remote.rmi.RMIConnection;
import javax.management.remote.rmi.RMIServer;

public class Rmi {

    public static void main(String args[]) throws Exception {
        // We need a Security Manager (not necessarily an RMISecurityManager)
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
        //
        // Define a registry (this is just about building a local data structure)
        // 
        final int comSunManagementJmxRemotePort = 9001;
        Registry registry = LocateRegistry.getRegistry("<JMX server IP address>", comSunManagementJmxRemotePort);
        //
        // List registry entries. The client connects (using TCP) to the server on the
        // 'com.sun.management.jmxremote.port' and queries data to fill the local registry structure.
        // Among others, a definition for 'jmxrmi' is obtained.
        //
        System.out.print("Press enter to list registry entries");
        System.in.read();
        String[] names = registry.list();
        for (String name : names) {
            System.out.println("In the registry: " + name);
        }
        //
        // 'Looking up' the entry registered under 'jmxrmi' involves opening and tearing down
        // a TCP connection to the 'com.sun.management.jmxremote.port', as well as a TCP
        // connection to an ephemeral secondary port chosen at server startup.
        // The actual object locally obtained is a "javax.management.remote.rmi.RMIServerImpl_Stub"
        // indicating where the ephemeral port is.
        // "RMIServerImpl_Stub[UnicastRef [liveRef: [endpoint:[$IP:$EPHEMERAL_PORT](remote),objID:[-62fb4c1c:131a8c709f4:-7fff, -3335792051140327600]]]]"        
        //
        System.out.print("Press enter to get the 'jmxrmi' stub");
        System.in.read();
        RMIServer jmxrmiServer = (RMIServer)registry.lookup("jmxrmi");
        System.out.println(jmxrmiServer.toString());
        //
        // Now get a "RMI Connection" to the remote. This involves setting up and tearing
        // down a TCP connection to the ephemeral port. 
        //        
        System.out.print("Press enter to get the 'RMIConnection'");
        System.in.read();
        RMIConnection rcon = jmxrmiServer.newClient(null);
        //
        // Ask away. This involves setting up and tearing
        // down a TCP connection to the ephemeral port. 
        //
        System.out.print("Press enter to get the 'domains'");
        System.in.read();
        for (String domain : rcon.getDomains(null)) {
            System.out.println("Domain: " + domain);
        }
        //
        // Ok, that will do. For serious applications, we better use the higher-level JMX classes
        //
    }   
}
于 2011-08-08T16:48:51.440 に答える
6

実際には、JMX がランダムなポート番号でリモート アクセス可能なコネクタを強制的に作成するために使用できる、文書化されていないプロパティがあります。

-Dcom.sun.management.jmxremote.authenticate="false" 
-Dcom.sun.management.jmxremote="true" 
-Dcom.sun.management.jmxremote.ssl="false" 
-Dcom.sun.management.jmxremote.port="0"
-Dcom.sun.management.jmxremote.local.only="false"

最後の 2 つのプロパティは最も重要です。

于 2011-11-25T08:22:03.443 に答える
3

ドキュメントは、次のプロパティを指定しない限り、JMX エージェントがローカルの一時ポートを使用することを示しているようです。

com.sun.management.jmxremote.port=portNum

1 つのシステムに多数のJava アプリケーションを配置できるため、デフォルト ポートは使用されません。また、デフォルト ポートがあったとしても、管理できるアプリケーションは 1 つだけです。上記の構成プロパティは、リモート管理を明確に目的として提供されています。

エフェメラル ポートを使用する必要がある場合は、次のシステム プロパティを使用して、JMX エージェントの URL に JVM 内からアクセスできる必要があります (ただし、これはローカル アドレスである可能性があります)。

com.sun.management.jmxremote.localConnectorAddress

: リモートで利用可能なアドレスでソケットを開いて、ローカル ソケットにプロキシ リクエストを送信することはいつでもできると思いますが、利用可能なオプションを使用する方がはるかに魅力的です。

于 2009-02-05T15:15:53.363 に答える
2

私は最近、特別なプロパティを設定してJVMを起動しなくても、JavaコードからリモートJMX管理を有効にする方法を理解するために取り組んでいます。私が決めた解決策は、自分のプライベートRMIレジストリを(十分に簡単に)開始し、そのレジストリでJMXサービスを公開することです。独自のMBeanServerを作成してから、新しいJMXConnectorServerを作成します。JMXConnectorServerは、次のような呼び出しによって作成されます。

connector = JXMConnectorServerFactory.newJMXConnectorServer(url, null, server);

ここで、serverはMBeanServerであり、urlはJMXServiceURLのインスタンスです。

URLの形式は「service:jmx:rmi:/// jndi / rmi:// localhost:/ jmxrmi」です。ここで、portは(ローカル)プライベートレジストリのポート番号です。「jmxrmi」は、JMXサービスの標準サービス名です。

これを設定してコネクタを起動すると、hostname:portを使用してjconsoleから接続できることがわかりました。

これは私のニーズに完全に対応しています。誰かがこのアプローチに欠陥を見ているかどうか知りたいと思います。

参照:JMXチュートリアル、Chap。3

于 2012-07-23T18:21:05.913 に答える
0

Glassfish アプリケーション サーバー内でアプリケーションを実行する場合は、単に次の asadmin コマンドを実行します。変更を有効にするには、実行中のすべてのサーバーを再起動する必要があります。

./asadmin enable-secure-admin

セキュリティをさらに有効にする追加の Glassfish サーバー構成があります。詳細については、JMX を介して Glassfish にリモートで接続するを参照してください。

于 2015-03-20T22:48:32.917 に答える