RemoteCache & RemoteCacheServerFactory setting RMISocketFactory
---------------------------------------------------------------

                 Key: JCS-41
                 URL: https://issues.apache.org/jira/browse/JCS-41
             Project: JCS
          Issue Type: Improvement
          Components: RMI Remote Cache
    Affects Versions: jcs-1.3, jcs-1.4-dev
         Environment: All
            Reporter: Niall Gallagher
            Assignee: Aaron Smuts


Classes...

org.apache.jcs.auxiliary.remote.RemoteCache
and
org.apache.jcs.auxiliary.remote.server.RemoteCacheServerFactory

.. both try to set a timeout on RMI connections between the remote cache server 
and client machines using the following code to install a timeout-enabled 
socket factory which the RMI subsystem subsequently uses...

        RMISocketFactory.setSocketFactory( new RMISocketFactory() {
            public Socket createSocket( String host, int port ) throws 
IOException {
                Socket socket = new Socket( host, port );
                socket.setSoTimeout( DEFAULT_RMI_SOCKET_FACTORY_TIMEOUT_MS );
                socket.setSoLinger( false, 0 );
                return socket;
            }

            public ServerSocket createServerSocket( int port ) throws 
IOException {
                return new ServerSocket( port );
            }
        });

The socket factory code above applies a "read timeout" to RMI sockets such that 
if a connection is already established and subsequently stalls or a machine 
goes offline, the timeout will break the connection as intended. The code does 
not apply a "connect timeout" however, which means that if an attempt is made 
to establish a new connection to a machine which is offline, the socket 
connection attempt will stall for an infinite amount of time (such is the 
default connect timeout), and therefore the thread opening the connection will 
stall permanently in the JVM.

This is not a bug in JCS code, it was a limitation in JDK3 in that you could 
not AFAIK set a connection timeout on a socket.

As of JDK4, there is a socket.connect(address, timeout) method, so this issue 
can be fixed.

Here's the required replacement code:

        RMISocketFactory.setSocketFactory( new RMISocketFactory() {

            public Socket createSocket( String host, int port ) throws 
IOException {
                Socket socket = new Socket();
                socket.setSoTimeout(timeoutMillis);
                socket.setSoLinger( false, 0 );
                socket.connect(new InetSocketAddress(host, port), 
timeoutMillis);
                return socket;
            }

            public ServerSocket createServerSocket( int port ) throws 
IOException {
                return new ServerSocket( port );
            }
        });

This was an issue for us recently. We fixed it by installing the 
RMISocketFactory above in the JVM before initializing JCS. We have tested and 
confirmed that this code works well with JCS, it times out reads same as before 
and it now times out new connection attempts too.

How about including this in the next version of JCS?

By the way I read some JCS mailing list archives from last time socket timeouts 
were discussed. Not sure if this will be helpful to anyone... but we found that 
if an RMI client and server were running on the same subnet, timeouts were not 
required and each machine detected that the other was offline immediately. 
Cross-subnet through our router however, timeouts became important as attempts 
to connect to an offline machine resulted in JCS threads hanging whilst trying 
to connect.

We are not sure, but we suspect that this is related to our firewall blocking 
required ICMP "host not reachable" packets between subnets, causing different 
behaviour depending on the network setup. The replacement code above allows our 
machines in both subnets to recover when a machine is offline, previously they 
just stalled. 

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to