今天在发布线上版本的时候发现一个rmi的异常,开始一看以为是客户端配置出错,但检查配置后发现配置无异常.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
org.springframework.beans.factory.support.DefaultListableBeanFactory[line:242]- Returning cached instance of singleton bean 'callbackService' org.springframework.remoting.rmi.RmiClientInterceptorUtils[line:182]- Remote service [rmi://10.77.7.49:9200/callbackService] threw exception java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is: java.net.ConnectException: Connection refused at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:601) at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:198) at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184) at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:110) at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178) at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132) at $Proxy24.invoke(Unknown Source) at org.springframework.remoting.rmi.RmiClientInterceptor.doInvoke(RmiClientInterceptor.java:398) at org.springframework.remoting.rmi.RmiClientInterceptor.doInvoke(RmiClientInterceptor.java:344) at org.springframework.remoting.rmi.RmiClientInterceptor.invoke(RmiClientInterceptor.java:259) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) at $Proxy23.process(Unknown Source) at java.lang.Thread.run(Thread.java:662) |
很奇怪为什么会去连接127.0.0.1,因为配置中就没有配置这一项.
找到org.springframework.remoting.rmi.RmiServiceExporter源码,找到关键导出类UnicastRemoteObject,我们做了如下测试,
1 2 3 4 5 6 |
@Test public void testUnicastRemoteObject() throws RemoteException { System.err.println(UnicastRemoteObject.exportObject(new Remote() {}, 0)); } |
1 2 3 |
Proxy[Remote,RemoteObjectInvocationHandler[UnicastRef [liveRef: [endpoint:[127.0.0.1:54167](local),objID:[3824563c:137eb525b2a:-7fff, 7280001563407204648]]]]] |
这表明对象在没有注册出去的时候其IP就已经决定,当绑定以后客户端就按照此IP去查找.
这里有几个解决方案
- 在java Main中增加参数,即改为,java -Djava.rmi.server.hostname=192.168.1.101 Main
- 在初始化时增加如下代码,System.setProperty(“java.rmi.server.hostname” , “192.168.1.101” );
- 使用tomcat时,需要在catalina.sh最前面加入如下脚本,JAVA_OPTS=”-Djava.rmi.server.hostname=ip”
rmi在使用过程中确实很便利,但在可用性和高并发下还是有劣势,使用时候仍需要注意.