Okay, so am I right in thinking i'd have the following: A server interface, a server implementation, and a master server which creates the three servers (with unique names) and finally a client?
- The 'master server' needs to create a Registry on its own localhost, bind itself to the Registry so the slave servers can find it, and export a remote interface that lets the servers register themselves with it.
- The master server must do the binding to this Registry on behalf of the slaves, as you can't bind to a remote Registry. But in fact the slaves don't need to be bound to the Registry at all, only registered with the master.
- The master needs to export a second remote interface that provides the API to the client, which provides the upload API and whose implementation performs the balancing act. I would keep this interface separate from the interface used by the slaves, both for security reasons and for simplicity: you don't need clients trying to be slaves, or worrying about what the slave-relevant methods in the remote interface are.
- All these servers and registries can run on port 1099.
- The slaves are presumably multiple instances of the same service, so they all use a common remote interface. This interface provides the upload-to-slave API, and it also needs to allow each slave to provide the knowledge about how full each slave is, possibly as a return value from the upload method, or else as a query method.
Quick sketch:
public interface UploadMaster extends Remote
{
void upload(String name, byte[] contents) throws IOException, RemoteException;
}
public interface LoadBalancingMaster extends Remote
{
void register(Slave slave) throws RemoteException;
void unregister(Slave slave) throws RemoteException;
}
public interface Slave extends Remote
{
/** @return the number of files now uploaded to this slave. */
int upload(String name, byte[] contents) throws IOException, RemoteException;
int getFileCount() throws RemoteException;
}
I hope this is homework. RMI is a poor choice for file transfer, as it bundles up the entire argument list into memory at both ends, rather than providing a streaming interface.