Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: THEend8_
CS4103 Distributed Systems: Coursework Practical – Phase 2
Recommended completion: end of Week 5
Implement a message-passing system with a strict total ordering of messages
The goal is to have different browser windows communicating via the server process. To
achieve this, each browser window will act as a different process, each with its own id. The
server will preserve a message pool of in-transit messages. Instances of a shared message
class should be passed through the service interface, via calls to send and receive methods.
The application should look something like this, just to give an outline idea. Obviously (!)
don’t spend any serious time on making it look nice.
The following text explains how this can be achieved using the GWT and Servlet
architectures.
Servlets, GWT etc
As explained elsewhere, a single instance of the Java servlet is initialised at the first call to
any of its service methods, and this stays extant until it is closed down by the server at some
later time - typically when it hasn’t received any traffic for a long period. For the purposes of
this project, this shouldn’t be an issue1 and you can assume that the class persists for the
duration of its use.
As all requests are served by a single servlet class instantiation, that object can provide
shared state among different its clients. To allow message passing, all that is required is for
the server class to maintain a pool of messages; a “send” from a client should add a new
message to the pool, and a “receive” from a client should find a message destined for that
client (if there is one), remove it from the pool, and return it to the client. If there is more
than one message waiting for the client, it is up to you to decide which gets returned, but
remember Lamport’s assumption that messages between the same two nodes will arrive in
the order that they are sent.
Be aware that the server implementation class must not have an explicit constructor. To
initialise the state it’s normal to provide code for an “init” function that is called by the
servlet manager when the class is initialised.
All clients will require to have unique process ids; this can be achieved by the server class
maintaining an integer for that purpose which is incremented and returned during an initial
“registration” call from the client. As the author of a distributed system you should be
aware that already this is already not necessarily safe, as two clients may make interleaved
calls to this code! However it is the case that a Java integer increment-in-place operation
will not be interrupted – in fact all scalar types in Java are “thread safe”.
It is recommended to encode the messages as a simple Java class. Make sure this is in the
“shared” package of the GWT project, implements the gwt.IsSerializable interface2, and
doesn't have an explicit constructor.
If the server is maintaining a collection of such objects, it is best to make sure that this is
thread safe. Although it’s possibly a reasonable assumption that it doesn’t matter - only a
small number of calls are likely to be made, and each call is likely to take very little time at
the server. But always remember that concurrent access to any collection type is undefined,
which makes things very, very hard to debug when it happens… For collection types in Java
it’s easy to ensure safety, see the example in my slides.
To see what is happening at the server side, the server process can write the development
mode console. It can just use the System.out object for this purpose; java.util logging is also
available server-side. Or if you’re ambitious you can have a dedicated process querying the
server.
Interfaces
The overall view of the system should be several browser windows, one representing each
process, which communicate with each other via the server.
The interface within each browser window can be extremely simple. For example, both send
and receive events could be triggered by user buttons. It would be nice to display a text log
of things like messages sent and received.
1 The programmer can supply methods which will be executed at startup and shutdown when initiated by the
servlet manager, so it is possible to arrange for state to be stored and retrieved between invocations. This is
not necessary for this project.
2 n.b. this is different from Java Serializable – which will almost always, but not quite always, work. As always
spell serializable with a “z”…
The minimal service functionality would be register (for a client to receive a unique id from
the server), send, and receive. To add a little sophistication, it would be nice for receive to
be a separate client-side thread (for which you need to use the gwt.Timer, not the Java
Thread, class – remember all the client-side Java code is compiled into JavaScript, and
JavaScript on a browser is not multi-threaded!) which regularly polls for new messages. It
would also be nice for each process to learn from the server when other new clients are
registered, so that messages are only sent to clients that exist (or, rather, as always in a
distributed system, have existed at some point in the past!) This could be via a normal
message receive sent from the server, or a separate service call. However, given the context
of the exercise it’s also quite reasonable just to type a process id into the message send
interface, as we’re not really expecting this application to be distributed over the Internet!
Message content
We will be re-using this framework for the next part of the practical exercise, so it would be
good to have a relatively generic message class, which of course can be extended to allow
different message types and payloads. The only requirement at this stage is for each
message to have a timestamp, so that Lamport’s strict global ordering can be imposed on
the set of messages passed during a session.