2012-05-02 3 views
3

간단히 말해 RMI 서버와 클라이언트가 있습니다. Server와 Client는 서로 RMI 호출을 할 수 있습니다. 클라이언트가 서버에 연결되면 서버는 클라이언트에서 수 백 번의 메서드 호출을 빠르게 수행 할 수 있습니다.RMI 메서드 호출이 간헐적으로 실패 할 수있는 원인은 무엇입니까?

큰 문제가있는 Server-to-Client 메서드 호출이 끝날 무렵, RMI는 Server-Client에서 연결을 설정할 수 없기 때문에 일부는 실패합니다. 성공할 것이다. 이 프로젝트가 오히려 큰 (약 50K 라인) 때문에 나는 실제 코드를 게시 할 수 없습니다, 그러나 여기에 슬로우됩니다 예외의 전체 스택 추적입니다 :

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 

내가 훨씬을 제공 할 수 없습니다, 다시 죄송합니다 코드의 방법이지만, 필자는 반드시 코드 수정을 요구하지는 않습니다. 왜 이런 일이 일어날지를 고민하고 싶습니다.

편집

추가 된 전체 스택 추적.

+0

당신을 도울 수 있습니다 : http://docs.oracle.com/javase/jndi/tutorial/objects/storing/remote.html –

+0

내 질문에 약간 어리석은 일이있을 수 있지만 클라이언트에 예외가 있는지 확인 했습니까? 측면? –

+0

@MartinPrakash 예, 그렇습니다. 이것은 * 클라이언트 측에서 예외입니다. – EJP

답변

6

거의 모든 머리카락을 뽑아 낸 후 RMI가 너무 많은 포트를 열려고 시도 했음이 밝혀졌습니다. 후드 아래에서 사용자 정의 RMISocketFactory 구현을 사용하고 있습니다. 이 사용자 정의 구현은 싱글 톤이므로 hashCode()equals()을 구현해야한다고 생각하지 않았습니다. 실제로 매우 고통스러운 실수 ...

RMI는 소켓을 생성해야하는 소켓이 소켓을 생성 한 공장과 동일하지 않은 RMISocketFactory으로 생성되어야한다고 RMI에서 판단한 경우 소켓을 재사용하지 않습니다. 재사용하고 싶어합니다. RMI는 equals()hashCode()에 의존하여이 검사를 수행합니다. 사용자 정의 소켓 팩토리에서이 두 메서드를 올바르게 구현하면 이러한 간헐적 인 문제가 사라졌습니다.

이 문제의 설명은 여기에서 찾을 수 있습니다 : 어떤 속도에서

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

이, 이것 좀 봐 복용에 대한 모든 덕분에, 나는 확실히 당신의 시간을 주셔서 감사합니다!

추가 정보

밝혀, 나는 또한 연결에 기여 들어오는 연결 요청에 대한 큐 공간이 부족하고 사용 된 ServerSocket이 삭제된다. 생성자 new ServerSocket(port, newConnectionQueueSize, bindAddress)이 큰 newConnectionQueueSize과 함께 사용하면이 문제도 해결됩니다.

관련 문제