- To fetch a stub from the remote RMI registry, and
- To make a method call to the server using the stub
too many open files
" error. This occurs if your client is making lots of quick RMI calls to lots of different remote servers and there isn't enough time for the opened RMI sockets to close. (I think sockets are closed if they have been idle for at least 15 seconds). As a result, you run out of "file descriptors" and aren't able to make any more remote calls, until some have freed up. This can be a pain and you have to get your Unix SA to increase the ulimit
on the client host, in order make more remote connections.
In this post, I will describe how you can use a cache to halve the number of remote calls you make. So instead of fetching a new stub each time, simply fetch the stub the first time and store it in a local stub cache (e.g. in a hash table in memory). The second time you need to make a remote call, the stub is already available locally and, hence, only one remote method invocation is necessary. BUT the stub may not be valid (e.g. if the server has been restarted). If the stub isn't valid, an instance of RemoteException
will be thrown when client attempts to use it to make a remote method call. In this case, the stub should be removed from the cache and a remote lookup performed to get a fresh one.
RemoteCache.java
import java.net.MalformedURLException; import java.rmi.NotBoundException; import java.rmi.Remote; import java.rmi.RemoteException; import java.util.Hashtable; import java.util.Map; /** * A local Remote stub cache * Instead of fetching stubs each time over the network, * simply fetch them the first time and store them in a * local cache. * * @author Fahd Shariff */ public class RemoteCache { private static Map<String,Remote> cache = new Hashtable<String, Remote>(); /** * Returns a stub to the remote object. * This method first checks the cache * and if not found, looks up in the registry * * @param serverDescription the url to the server * @return a stub to the remote object * @throws MalformedURLException * @throws RemoteException * @throws NotBoundException */ public static Remote get(String serverDescription) throws MalformedURLException, RemoteException, NotBoundException { Remote toReturn=cache.get(serverDescription); if (toReturn==null) { toReturn=(Remote)RMIRegistry.lookup(serverDescription); if (toReturn!=null) { cache.put(serverDescription,toReturn); } } return toReturn; } /** * Removes the specified Remote Object from the cache. * * @param serverDescription */ public static void remove(String serverDescription) { cache.remove(serverDescription); } }Using the RemoteCache
The following code snippet shows how you use the
RemoteCache
to obtain a stub. There is a simple retry loop - if a RemoteException occurs, the invalid stub is removed from the cache and a fresh one is obtained.
String url = "rmi://remotehostname:2138"; while(retries<MAX_RETRIES){ try{ MyRemoteObject remoteObj = (MyRemoteObject) RemoteCache.get(url); remoteObj.callMyMethod(); break; } catch(RemoteException e){ //stub is invalid, so remove and retry RemoteCache.remove(url); retries++; } }References:
Seamlessly Caching Stubs for Improved Performance
Expiring Data with Hashbelts
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.