Making multiple instances of a RMI method in (from?) one server implementation

Lenny Wintfeld <[email protected]> Tue, 5 Jun 2007 18:13:24 -0400
Newsgroups gmane.comp.java.sun.rmi
Message-ID <[email protected]>
I'm starting on a JavaSE RMI application and having some trouble working
out some points in the architecture. Let me first lay our what I'm
trying to accomplish, then let you know where I'm at and finally ask the
2 specific questions I need answered.

I have fully functioning program that processes data sets that are given
to it at random times. It takes a few minutes to an hour to process each
data set into a result set.  Instead of  processing each data set in
sequence, my goal is to hand out data sets, one set to each available
computer on a lan segment, and then collect the results sets as they
become available for further organization, storage and distribution.
This way I'll be processing data sets in parallel, to the limit of the
number of computers on the lan. Data sets in excess of the number of
computers available would be queued, waiting for a computer to become
available  to process them.

I have a partial design which I've implemented in skeletal  form just to
get a better understanding of RMI and remote synchronization. I have a
single  "distributor" program and a set (actually 2 for now) of  data
"processor" programs. The "distributor" has a threadsafe incoming queue
which  holds the names of  data "processor" programs that are available
to process a data set. The names are submitted to the queue by the
"processor" programs when they become idle. I pull names out of that
queue and call the instance of the data "processor" program
corresponding to that name using  RMI. Since the one "distributor" and
the multiple "processor" programs access services from one another using
RMI they act as both server and client to one another. At this point I
have this bare skeleton of  a  subsystem (without doing any actual
processing of data) working ok.

The two inter-related design problems I'd like advice on have to do with
devising a method for the data "processor" instances to return their
result sets to the "distributor" once they're done.

Problem 1: There is no guarantee that a data "processor" will succeed in
sending its result set to the "distributor" (the "processor" program,
the vm its running on, the computer hosting the vm or the communications
link can all die). And I'm afraid that if a "processor" program crashes
while sending its result set back to the "distributor" no other
"processors" will be able to send their result sets (e.g. that a single
failure while sending to a synchronized method on the "distributor" will
kill the whole system). Is this a valid concern? If so, maybe each data
processor ought to have an individual point of contact with the
distributor for the purpose of returning its result set. This way if one
processor dies while "owning" the interface to the "distributor" other
"processors" can still send their result sets; since they each have a
separate data return point.. But how would I do this? Could I make a
thread in the "distributor" for each "point of contact" between each
"processor" and the "distributor"? If so, how is something like that
mechanized?  I can't imagine that the "distributor" thread could pass
its "this" pointer as an arg to an RMI method on another vm on another
computer and have it resolve to something usable. So am I woried aobut a
real problem or not ? And if so, is there a way  (hopefully a simple,
easy to implement way) to accomplish my goal of reliably reporting
result sets to the distributor. (Remember I'm not interested in
reporting result sets in parallel,  just getting result sets from all
live data "processors" eventually, even if a "processor" fails while
reporting its results) ?

Problem 2: The results set produced by the "processor" may be quite
large.  Large enough that the results can't be sent as the RMI method
return value from the call  to the "processor". The vm runs out of
memory (at least in Eclipse it does) when I try and return a a test byte
array of 10MB from the "processor" method. Instead, I'm thinking that
I'd  like to send the results over to the "distributor" piecemeal, by
defining a "resultReciever" RMI method in the "distributor" that the
"processor" could call as many times as necessary to move its whole
result set.  The method signature would look something like

public void resultReceiver(int blockNr, int blockTotal, int byteCnt,
byte[] result);

Where blockNr is the sequence number of the current block being sent,
blockTotal is the number of the last block that will be sent, byteCnt is
the size of the current block being sent and result is the data block
itself. To make sure that no blocks are missing I'd keep a lastBlockNr
in each instance of the object that implements the thread containing the
resultReceiver method at the "distributor". Does this sound like a
reasonable approach?

Thanks in advance for your advice.

Lenny Wintfeld

===========================================================================
To unsubscribe, send email to [email protected] and include in the body
of the message "signoff RMI-USERS".  For general help, send email to
[email protected] and include in the body of the message "help".

For a list of frequently asked RMI questions please refer to:
http://java.sun.com/j2se/1.3/docs/guide/rmi/faq.html

To view past RMI-USERS postings, please see:
http://archives.java.sun.com/archives/rmi-users.html