我目前正在使用 com.sun.management.jmxremote.*
属性启动我的Java VM,以便我可以通过JConsole连接到它以进行管理和监控。不幸的是,它会监听机器上的所有接口(IP地址)。
在我们的环境中,通常情况下,同时在一台计算机上运行多个Java VM。虽然可以告诉JMX监听不同的TCP端口(使用com.sun.management.jmxremote.port
),但最好让JMX使用标准的JMX端口并绑定到特定的IP地址(而不是所有的IP地址)。
这样可以更容易地找出我们通过JConsole连接到哪个VM(因为每个VM实际上“拥有”自己的IP地址)。有没有人想出如何让JMX监听单个IP地址或主机名?
答案 0 :(得分:22)
如果有其他人会因此而失去神经...... 10年后,他们终于解决了这个问题!
由于Java 8u102 -Dcom.sun.management.jmxremote.host
绑定到选定的IP
答案 1 :(得分:8)
费尔南多已经提供了my blog post :)的链接..这不是微不足道的。您必须提供自己的RMIServerSocketFactoryImpl,在所需地址上创建套接字。
如果内部/外部接口出现问题,并且您具有本地访问权限,则可能更容易设置本地防火墙。
答案 2 :(得分:0)
我还没有尝试过,但这可能有所帮助。
这里主要的麻烦是没有简单的方法来指定主机IP 要绑定到JMX的地址,它将始终绑定到所有接口。该 ' java.rmi.server.hostname'财产不起作用,我不想选择 同一主机上所有不同实例的不同端口。
另外,我不想创建自己的RMIServerSocketFactory 与之相关的复杂性,我是对现有代码的一个简单补丁。
我通过修补默认的JVM RMI套接字工厂来解决这个问题 负责创建此服务器套接字。它现在支持新的 ' com.sun.management.jmxremote.host'属性。
要使其工作,请将下面的Java代码保存到名为的文件中 太阳/ RMI /运输/代理/ RMIDirectSocketFactory.java。
从中编译并创建jmx_patch.jar并将其放入tomcat lib / 文件夹中。
然后,您需要将以下行添加到bin / setenv.sh:
CLASSPATH = $ CLASSPATH:$ CATALINA_HOME / LIB / mx_patch.jar
在tomcat实例启动中添加此选项
-Dcom.sun.management.jmxremote.host = 192.168.100.100"
然后,这将仅将JMX服务绑定到地址192.168.100.100。另外两个 随机RMI侦听端口仍将绑定到所有接口,但这很好 因为他们总是选择一个自由港。
现在,您可以在一台主机上运行多个tomcat实例 默认端口完好无损(例如,所有JMX都是8080)。
package sun.rmi.transport.proxy;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.server.RMISocketFactory;
public class RMIDirectSocketFactory extends RMISocketFactory {
public Socket createSocket(String host, int port) throws IOException
{
return new Socket(host, port);
}
public ServerSocket createServerSocket(int port) throws IOException
{
String jmx_host = System.getProperty("com.sun.management.jmxremote.host");
String jmx_port = System.getProperty("com.sun.management.jmxremote.port");
// Allow JMX to bind to specific address
if (jmx_host != null && jmx_port != null && port != 0 && integer.toString(port).equals(jmx_port)) {
InetAddress[] inetAddresses = InetAddress.getAllByName(jmx_host);
if (inetAddresses.length > 0) {
return new ServerSocket(port, 50, inetAddresses[0]);
}
}
return new ServerSocket(port);
}
}
答案 3 :(得分:0)
我刚试过
-Dcom.sun.management.jmxremote.host =
使用openjdk 1.8,效果很好。它与该addess绑定(根据netstat),所有看起来都正确(并且有效)。
答案 4 :(得分:0)
当只使用com.sun.management.jmxremote.host
而不改变com.sun.management.jmxremote.ssl
(默认为true
)或com.sun.management.jmxremote.registry.ssl
(默认为false
)时,它仍然会绑定到所有接口com.sun.management.jmxremote.port
,并且只会将 com.sun.management.jmxremote.host
用于 com.sun.management.jmxremote.rmi.port
(默认为随机端口)。不知道为什么会这样,它看起来像一个错误。对于这些 jmxremote.ssl
和 jmxremote.registry.ssl
值的任何其他组合,它将为两个端口正确使用给定的 jmxremote.host
。
例如,与
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.port=1234
-Dcom.sun.management.jmxremote.host=interface1
它仍然会绑定到端口 1234
的所有接口,并且只绑定到随机 interface1
的 jmxremote.rmi.port
。
请注意,JMX 客户端首先连接到 jmxremote.port
,这是一个 RMI 注册中心,通过它接收实际的 JMX 服务器端口 jmxremote.rmi.port
,因此客户端仍然能够与实际的JMX 服务器仅通过 jmxremote.host
接口。然而,仍然不希望 RMI 注册表监听所有接口,因为当不同的 VM 以相同的 jmxremote.port
值启动时会导致端口冲突,就像这个问题中的场景一样。
答案 5 :(得分:-3)
接受的答案很古老。有一些迹象表明Java现在提供了一些选项来实现这一点。比如我见过:
-Djava.rmi.server.hostname=<YOUR_IP>
......以及......
-Dcom.sun.management.jmxremote.host=<YOUR_IP>
但是,至少在我的系统jdk 1.7下,这些似乎没有任何影响 - JMX连接器仍然绑定到*。将非常感谢更新的答案(具有特定的适用版本)。这个应该很简单。