什么可能导致RMI方法调用间歇性失败? [英] What could cause RMI method calls to fail intermittently?

查看:146
本文介绍了什么可能导致RMI方法调用间歇性失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

长话短说,我有一个RMI服务器和客户端。服务器和客户端能够相互进行RMI调用。在客户端连接到服务器之后,服务器可以在客户端上快速连续地进行数百个方法调用。

Long story short, I have an RMI Server and Client. The Server and Client are capable of making RMI calls on each other. After the Client connects to the Server, the Server may make many hundreds of method calls in quick succession on the Client.

问题是这个 - 接近一个巨大的结尾批量的服务器到客户端方法调用,有些会失败,因为RMI声称它无法建立从服务器到客户端的连接,即使它之前的数百个调用将成功。我不能发布任何真正的代码,因为这个项目相当大(大约50k行),但这里是抛出异常的完整堆栈跟踪:

The problem is this - towards the end of a huge batch of Server-to-Client method calls, some will fail because RMI claims it cannot establish a connection from Server-to-Client, even though hundreds of calls before it will succeed. I can't post any real code because this project is rather large (about 50k lines), but here's the full stack trace of the exception that gets thrown:

java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is:
java.net.SocketException: Connection reset
at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source)
at sun.rmi.transport.StreamRemoteCall.executeCall(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.findClassDefinition(Unknown Source)
at com.fabric.network.NetworkClassLoader.findClass(NetworkClassLoader.java:111)
at java.lang.ClassLoader.loadClass(Unknown Source)
at com.fabric.network.NetworkClassLoader.loadClass(NetworkClassLoader.java:131)
at java.lang.ClassLoader.loadClass(Unknown Source)
at com.fabric.network.MessageSocket$CustomObjectInputStream.resolveClass(MessageSocket.java:171)
at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io.ObjectInputStream.readClassDesc(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
at java.io.ObjectInputStream.readSerialData(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
at java.io.ObjectInputStream.readSerialData(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at com.fabric.network.MessageSocket.receive(MessageSocket.java:118)
at com.fabric.application.driver.NodeRemoteDriver$IncomingMessageThread.run(NodeRemoteDriver.java:205)
Caused by: java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is:
java.net.SocketException: Connection reset
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 $Proxy2.findClassDefinition(Unknown Source)
at com.fabric.network.ClassDefinitionCache.findClassDefinition(ClassDefinitionCache.java:78)
at com.fabric.management.host.NodeManagementServices.findClassDefinition(NodeManagementServices.java:231)
at sun.reflect.GeneratedMethodAccessor16.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.io.BufferedInputStream.fill(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
at java.io.DataInputStream.readByte(Unknown Source)
... 21 more

再次,抱歉,我不能提供太多的代码,但我不是必需品我要求修复代码 - 我只是想了解为什么会发生这种情况。

Again, sorry I can't provide much in the way of code, but I'm not necessarily asking for a code fix - I just want to wrap my head around why this might be happening.

编辑

添加了完整的堆栈跟踪。

Added the full stack trace.

推荐答案

好的,所以几乎拔掉了我所有的头发事实证明,RMI试图打开太多端口。我正在使用自定义 RMISocketFactory 实现。这个自定义实现是一个单例,所以我认为没有必要实现 hashCode() equals()。确实是一个非常痛苦的错误...

Ok, so after nearly pulling all my hair out, it turns out that RMI was trying to open up way too many ports. I am using a custom RMISocketFactory implementation under the hood. This custom implementation is a singleton, so I didn't think it was necessary to implement hashCode() and equals(). A very painful mistake indeed...

事实证明,如果RMI确定需要创建的套接字是由<$创建的,RMI将不会重用套接字c $ c> RMISocketFactory 这不等同于创建它想要重用的套接字的工厂。 RMI依赖于 equals() hashCode()来执行此检查。一旦我在自定义套接字工厂中正确实现了这两种方法,这些间歇性问题就消失了。

Turns out, RMI won't reuse sockets if RMI determines that the socket it needs to create is to be created by an RMISocketFactory that isn't equivalent to the factory that created the socket it wants to reuse. RMI relies on equals() and hashCode() to perform this check. Once I correctly implemented these two methods in my custom socket factory, these intermittent problems went away.

可以在此处找到此问题的描述:

The description of this issue can be found here:

http:/ /docs.oracle.com/javase/7/docs/technotes/guides/rmi/faq.html

无论如何,多亏了所有的服用看看这个,我确定感谢您的时间!

At any rate, thanks to all for taking a look at this, I sure appreciate your time!

其他信息

我之前没有注意到的第二个问题是我使用的 ServerSocket 用完了传入连接请求的队列空间,这也导致了连接被丢弃。使用构造函数新的ServerSocket(port,newConnectionQueueSize,bindAddress)以及更大的 newConnectionQueueSize 也有助于解决此问题。

A secondary issue that I didn't notice before was that the ServerSocket I was using was running out of queue space for incoming connection requests, which also contributed to the connections being dropped. Using the constructor new ServerSocket(port, newConnectionQueueSize, bindAddress) with a larger newConnectionQueueSize contributed to solving this problem as well.

这篇关于什么可能导致RMI方法调用间歇性失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆