`
gaoc121
  • 浏览: 11006 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Spring的RMI连接问题

阅读更多

RMI 问题 1 背景:


./shutdown.sh 关闭 rmi 服务器的 tomcat ,然后 ./startup.sh 启动,客户端连接总是会导致如下错误:

org.springframework.remoting.RemoteLookupFailureException: Lookup of RMI stub failed; nested exception is java.rmi.UnmarshalException: error unmarshalling return; nested exception is:

        java.io.EOFException

com.ffcs.ieie.communicate.ieiemp.IeiempException: org.springframework.remoting.RemoteLookupFailureException: Lookup of RMI st

ub failed; nested exception is java.rmi.UnmarshalException: error unmarshalling return; nested exception is:

        java.io.EOFException

RMI 问题 1 分析:

The cause of the problem is the fact that Spring creates an RMIRegistry with the classloader of the server webapp. Then, when restarting the server, the RMIRegistry is not shut down. After the restart the Registry keeps its references to the old Stubs which do not exist anymore.
There are two solutions:
1) Start the rmiregistry in a seperate process without the classpath of the server app.
2) (better approach) Let spring start the RMIRegistry throu RmiRegistryFactoryBean, which shuts it down correctly.

参考: http://forum.springframework.org/showthread.php?t=33073

RMI 问题 1 解决:

将服务器中的 spring 配置代码,如下:

    < bean id = "incomingService" class = "com.ffcs.ieiemp.ieie.rmi.IncomingService" />

    < bean id = "rmiService" class = "org.springframework.remoting.rmi.RmiServiceExporter" >

        < property name = "serviceName" value = "IncomingService" />

        < property name = "service" ref = "incomingService" />

        < property name = "serviceInterface" value = "com.ffcs.ieiemp.ieie.rmi.Incoming" />

        < property name = "registryPort" value = "1099" />

</ bean >

替换为:

    <bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">

       <property name="port" value="1099"/>

    </bean>

    < bean id = "incomingService" class = "com.ffcs.ieiemp.ieie.rmi.IncomingService" />

    < bean id = "rmiService" class = "org.springframework.remoting.rmi.RmiServiceExporter" >

        < property name = "serviceName" value = "IncomingService" />

        < property name = "service" ref = "incomingService" />

        < property name = "serviceInterface" value = "com.ffcs.ieiemp.ieie.rmi.Incoming" />

        <!-- <property name="registryPort" value="1099"/> -->

        <property name="registry" ref="registry"/>

</ bean >

 

RMI 问题 2 背景:

          RMI 服务器重启,总是会出现客户端连接拒绝的问题。

RMI 问题 2 分析:

          服务器重启会影响到客户端?说明客户端有保存着重启之前的服务器连接相关记录。经研究发现,客户端 Stub 有缓存,所以只要刷新缓存即可解决问题。参考: http://forum.springsource.org/showthread.php?t=61575

RMI 问题 2 解决:

          在客户端连接代码中增加红色标识的代码:

       RmiProxyFactoryBean factory= new RmiProxyFactoryBean();

       factory.setServiceInterface(Incoming. class );

       factory.setServiceUrl(url);

       // XXX vincan: 解决重启 rmi 的服务器后会出现拒绝连接或找不到服务对象的错误

       factory.setLookupStubOnStartup(false );

       factory.setRefreshStubOnConnectFailure(true );

       factory.afterPropertiesSet();

    Incoming service=(Incoming)factory.getObject();

 

RMI 问题 3 背景:

          两台服务器, JDK 都是 1.6 ,在一个局域网内,内网 IP 分别为 192.168.39.11192.168.39.164 ,对应的的还有外网 IP 。写了一个 RMI 服务器和客户端,在本地调试没有问题。把服务器端布署到 11 这台服务器上后,在 164 客户端连接却总是抛错:
java.rmi.ConnectException: Connection refused to host:127.0.0.1; nested exception is:
java.net.ConnectException: Connection refused: connect
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source)
at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source)
at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source)
at sun.rmi.server.UnicastRef.invoke(Unknown Source)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod
(Unknown Source)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)
at $Proxy0.call(Unknown Source)
at RMI.Client.callRMI(Client.java:39)
at RMI.Client.main(Client.java:53)
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(Unknown Source)
at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket
(Unknown Source)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket
(Unknown Source)
... 9 more
也就是 IP 被指向 127.0.0.1 了,而客户端发起连接的时候 IP 绝对是写的 IP192.168.39.11

RMI 问题 3 分析:

这就是典型的服务器有多个 ip 引起的 rmi 连接问题。

RMI 问题 3 解决:

         解决方法有三:

1.       服务器端添加代码: System.setProperty("java.rmi.server.hostname""192.168.39.11" );

可写在全局监听器里成为全局变量。

2.  在 RMI 服务器上 root 身份登录,输入 Vi /etc/hosts ,在第一行添加 192.168.39.11     ieie

3.  若是用 spring, 则在 RmiServiceExporter 中添加属性 <property name="registryHost"  value="192.168.39.11" />

总结 :RMI固然好用,但得慎用,以上问题困扰甚久,终得解决:)

分享到:
评论
1 楼 xzcgeorge 2013-08-01  
  Thx.

相关推荐

    Spring RMI

    - **RMI超时设置**:可以配置RMI连接和操作的超时时间,防止因网络延迟导致的应用阻塞。 - **RMI缓存**:客户端可以缓存远程对象的引用,减少重复的远程查找操作。 - **负载均衡**:通过RMI注册表,可以将请求分发到...

    spring rmi应用

    而“rmiClient”则可能包含客户端代码,用于连接到服务器并调用远程服务。 在实际应用中,Spring RMI提供了许多优势,如自动异常处理、透明的事务支持、线程管理等。同时,它还能与其他Spring特性如AOP结合,实现如...

    spring rmi 小例子

    6. **源码分析**:在提供的压缩包文件`SpringRMI`中,可能包含了上述所有步骤的代码示例。通过阅读这些源码,你可以深入理解Spring RMI的工作原理,包括服务暴露、注册、代理创建等。 7. **工具使用**:在开发过程...

    spring RMI简单例子

    Spring RMI(Remote Method Invocation)是Java平台上的远程方法调用技术,结合Spring框架的特性,使得在分布式系统中调用远程服务变得更加便捷。在这个简单的例子中,我们将深入理解Spring RMI的工作原理以及如何...

    Spring Rmi使用文档

    在实际应用中,考虑到安全性问题,可能还需要配置防火墙规则、使用 SSL/TLS 加密连接等方式来增强 RMI 通信的安全性。 #### 四、Spring RMI 的应用场景 Spring RMI 适用于需要跨 JVM 或跨网络进行远程方法调用的...

    spring rmi 源码

    通过这种方式,Spring RMI简化了传统Java RMI的许多复杂性,包括异常处理、连接管理以及服务发现等。此外,由于Spring的IoC特性,服务端和客户端的组件可以轻松地替换或扩展,提高了系统的灵活性和可维护性。 总的...

    spring RMI 远程接口调用

    Spring RMI(Remote Method Invocation)远程接口调用是Spring框架提供的一个特性,它允许你在分布式环境中调用对象的方法,使得应用程序能够跨越网络边界操作远程对象。这个技术在大型企业级应用中尤其有用,因为它...

    spring+rmi非本地实现

    - **安全考虑**:在Web环境中,必须考虑到安全性问题,例如使用Spring Security来保护RMI接口,防止未经授权的访问。 - **负载均衡**:在大型分布式系统中,可能有多台服务器提供RMI服务。Spring可以配合负载均衡...

    RMI SpringRMI API

    在Spring 3.1版本中,通常会使用Spring的RMI支持,这可能涉及到的包包括Spring的核心库、AOP库、beans库以及RMI相关的库。确保这些库都在项目的`lib`目录下,以避免运行时的依赖问题。整合Spring和RMI可以让你更专注...

    java spring rmi

    客户端需要知道服务端的RMI服务地址,以便连接并调用远程方法: - 引入服务端的远程接口,并创建对应的代理类,通常使用Spring的`@RmiProxyFactoryBean`或`@Lookup`注解完成。 - 配置RMI服务的URL,如`rmijndi://...

    springRMI示例

    在这个示例中,`SpringRMIClient`可能是客户端的配置或测试类,它将通过RMI连接到服务器并调用`processBusiness`方法。`Test_SpringRMI`类可能就是执行这个任务的测试代码。 通过这样的设置,我们可以利用Spring ...

    spring rmi 简单应用

    同时,客户端的配置文件会包含RMI注册表的URL,以便于查找并连接远程服务。 源码分析是理解这一过程的关键。服务器端的`@ServiceExporter`注解会将服务实例暴露出去,客户端的`@RmiService`注解则会生成一个代理类...

    java spring+rmi 的远程调用例子

    例如,使用SSL加密通信、设置连接池来复用RMI连接、优化序列化机制等。 在这个“Spring+RMI”的示例中,开发者可能已经完成了上述步骤,并且经过测试确保了远程调用的正确性。通过学习和理解这些内容,你可以创建...

    spring中使用RMI

    通过Spring的配置,我们可以轻松地在客户端和服务器之间建立连接,实现远程方法调用,提高应用的可扩展性和灵活性。理解并熟练运用Spring的RMI支持,对于构建大型、分布式的企业级应用至关重要。

    基于Spring+hibernate+mysql+rmi+swing的登录Demo

    在登录Demo中,Spring负责管理各个组件的生命周期,如数据库连接、事务管理等,同时通过AOP实现跨切面的功能,如日志记录和安全控制。 其次,Hibernate作为持久化层的首选,它简化了Java对象与数据库表之间的映射...

    rmi实例(Spring整合)

    2. 性能优化:通过调整RMI连接池大小、缓存远程对象引用等方式,提高并发处理能力,减少网络开销。 **五、RMIClient子文件解析** "RMIClient"可能是项目中的一个客户端模块,负责与RMI服务器进行交互。这个模块可能...

    HTTP客户端,HTTP服务器,RMI客户端和服务器

    RMI客户端通过网络连接到RMI服务器,调用其注册的服务对象的方法。在实验中,你可能会学习到如何创建RMI服务接口,实现该接口的服务器端,以及在客户端如何查找和调用远程服务。 具体到实验文件"rmi",这可能是RMI...

    Java RMI 例子 和一些常见问题

    Java Remote Method Invocation(RMI)是Java平台中用于分布式计算的一种技术。它允许Java对象在不同的JVM(Java虚拟机)之间...在实际项目中,RMI可以与其他技术(如EJB、Spring框架)结合,构建更复杂的分布式系统。

Global site tag (gtag.js) - Google Analytics