Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring:无法从防火墙后面使用RMI连接到JMX服务器_Java_Spring_Jmx_Firewall_Nat - Fatal编程技术网

Java Spring:无法从防火墙后面使用RMI连接到JMX服务器

Java Spring:无法从防火墙后面使用RMI连接到JMX服务器,java,spring,jmx,firewall,nat,Java,Spring,Jmx,Firewall,Nat,我的Spring应用程序运行在NAT防火墙(pfSense)后面的机器上。机器的内部IP为a.b.c.d,NAT IP为w.x.y.z Spring配置的serviceUrl设置为端口1100上的我的内部IP(a.b.c.d),当我启动应用程序时,我提供以下交换机: -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=w.x.y.z -Dcom.sun.management.jmxremote.port=1099 -Dcom.su

我的Spring应用程序运行在NAT防火墙(pfSense)后面的机器上。机器的内部IP为
a.b.c.d
,NAT IP为
w.x.y.z

Spring配置的serviceUrl设置为端口
1100
上的我的内部IP(
a.b.c.d
),当我启动应用程序时,我提供以下交换机:

 -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=w.x.y.z -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
 -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=w.x.y.z -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.rmi.port=1099 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
如上所示,我设置了
-Djava.rmi.server.hostname=w.x.y.z
,以便能够通过NAT连接到应用程序。我还打开了机器防火墙上的相关端口,并设置了一个从
w.x.y.z:1100
a.b.c.d:1100

然后,当我尝试在
w.x.y.z:1100
上使用jconsole从网络外部连接到应用程序时,我得到一个
java.io.IOException:jmxrmi

 java.io.IOException: jmxrmi
at sun.tools.jconsole.ProxyClient.checkSslConfig(ProxyClient.java:236)
at sun.tools.jconsole.ProxyClient.<init>(ProxyClient.java:127)
at sun.tools.jconsole.ProxyClient.getProxyClient(ProxyClient.java:483)
at sun.tools.jconsole.JConsole$3.run(JConsole.java:524)
 Caused by: java.rmi.NotBoundException: jmxrmi
at sun.rmi.registry.RegistryImpl.lookup(RegistryImpl.java:136)
at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:409)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:267)
at sun.rmi.transport.Transport$1.run(Transport.java:177)
at sun.rmi.transport.Transport$1.run(Transport.java:174)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:556)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:275)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:252)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:378)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at sun.tools.jconsole.ProxyClient.checkSslConfig(ProxyClient.java:234)
有趣的是,我可以使用
telnet
连接到
w.x.y.z
上的两个端口(
1099
1100

我的Spring配置的相关部分是:

<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
    <property name="port" value="1100" />
</bean>
<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="registry">
    <property name="server" ref="mbeanServer" />
    <property name="objectName" value="connector:name=rmi" />
    <property name="serviceUrl" value="service:jmx:rmi://a.b.c.d:1100/jndi/rmi://a.b.c.d:1100/server" />
    <property name="environment">
        <props>
            <prop key="jmx.remote.jndi.rebind">true</prop>
        </props>
    </property>
</bean>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
    <!-- indicate to first look for a server -->
    <property name="locateExistingServerIfPossible" value="true"/>
</bean>

真的
注意:我没有使用任何servlet容器


编辑:第一个答案为我提供了解决具体问题的基础,可以在第二个答案中看到。

您使用
com.sun.management.jmxremote.port
定义的初始端口称为注册表端口,仅用于启动协商和确定下一个用于“real”的端口沟通。JavaRMI机制使用动态分配的端口,通常与防火墙不兼容

也就是说,对于JMX来说,可以解决这个问题

a) 使用系统属性锁定两个端口(需要Java 7)

b) 使用自定义代码请求特定端口。看见

另见:


详细阐述了我使用anttix在回答中给出的链接和指针确定的解决方案

因此,如上所述,使用系统属性
com.sun.management.jmxremote.port
com.sun.management.jmxremote.rmi.port
是解决方案的基础

我更改了Spring配置以删除
注册表
服务器连接器
bean,因为这不允许我注册端口
1099
PermissionExceptions
导致我无法绑定端口
1099
),并使用了平台mbean服务器

我使用的Spring配置如下所示:

 <bean id="mbeanServer" class="java.lang.management.ManagementFactory" factory-method="getPlatformMBeanServer"/>
java.rmi.server.hostname
设置为NAT VIP
w.x.y.z
非常关键,因为我们需要能够从网络外部对本地创建的远程对象执行远程操作


注意:此解决方案仅适用于Java 7u4或更高版本。

谢谢您的回答;使用它是有效的,我能够摆脱很多Spring配置。我希望你不介意我写我自己的答案,以你的答案为基础来解释我具体问题的解决方案。应同时设置com.sun.management.jmxremote.port和com.sun.management.jmxremote.rmi.port。要在AWS EC2上获得NAT VIP,请使用:
ip=$(curl-shttp://169.254.169.254/latest/meta-data/public-ipv4)
 <bean id="mbeanServer" class="java.lang.management.ManagementFactory" factory-method="getPlatformMBeanServer"/>
 -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=w.x.y.z -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.rmi.port=1099 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false