|
Concept
In short, YAMI is a project which objective is to
provide programmers
with a simple infrastructure for inter-object communication.
Of course, there are ready to deploy, free and commercial solutions,
some of them are backed by big organizations and are really well
designed - YAMI is not designed nor supposed to substitute them.
What could make YAMI competitive with other solutions is its simplicity
and ease of use in cases, where big, full-blown infrastructures are
just not necessary.
Here is a short description of three of the mainstream distributed
infrastructures that I knew at the time YAMI was born:
COM
In general, COM has nothing to do with Windows - it's a way of writing
programs. However, thanks to some commercial reasons, COM and Windows
are strongly connected, so whenever I say COM, I mean that
COM (the one from Windows).
COM works on MS Windows platform and is completely incorporated into
the operating system.
There is no need to have any library around, everything can be done
using the system API. It has some advantages (can use very low-level
features of the system to speed up communication, parameter marshalling
and so on), as well as disadvantages (allows interoperability between
objects when both parties involved are on the Windows systems). There
are bridges which allows to cross the platform and even technological
(I know that COM-CORBA communication is possible) boundaries, but they
add up to the complexity of the whole infrastructure.
Anyway, creating a small COM component that could communicate with
another component on the same machine or even on a different one is
quite easy (especially, using VB wizards...).
CORBA
I'm very impressed by the amount of work that OMG has put into it. And
probably it's the best choice for bigger systems or where objects have
to interoperate across different platforms (it's completely
platform-independent). There are free and commercial implementations
that can provide all the infrastructure for inter-object communication
and the whole idea with its specification seems very promising.
There is only one problem: it's so big, that apart from very simple
cases, it can appear to be overwhelming. Also, the ORB (the run-time
part of this infrastructure, which has to exist together with the
process hosting the communicating objects) tends to be quite fat. Even
in small, simple programs that need some communication infrastructure,
the ORB can add a few MBs to their size. I estimate, that in majority
of cases, it's too big.
But, as stated before, it's probably the best choice for
industrial-strength, big systems.
Java RMI
Well, it works only when all parties involved in communication speak
Java...
It's platform-independent, but not language-independent.
To be more exact: some of the readers keep correcting me that it is
possible to use JavaRMI from other languages, especially those that can
run on VM.
Whereas technically true, the general experience with this is not really wide.
If we concentrate only on mainstream uses, it is safe to associate RMI
with Java only.
This is exactly the reason, why I believe the simple, light, platform-
and language-independent, freely-available messaging infrastructure
would be the solution for quite a big part of object systems built
nowadays.
And this is just what the YAMI project is supposed to
provide.
Also, the objective of this project is not only to give the
ready-to-deploy solution, but also to invite other programmers
and people interested in object systems to participate in it, which can
mean everything from using, discussion to designing and development.
Description of the YAMI communication model
In all object systems, there is always a notion of the object.
YAMI is no different about that - let's define the object as any piece
of software that is able to send and/or reply to a message. And that's
all. There is no notion of a class or component. The object is anything
that can communicate, but to make things more neat, let's define some
schema or strategy to which all YAMI systems should stick.
There is one thing that makes YAMI different from other messaging
infrastructures.
COM, CORBA and JavaRMI go very far to hide as much as possible behind
the notion of object reference. In those systems, the client is
never aware of the location of the object. And this is the most
difficult thing to achieve and probably what makes them so hard to
implement. I believe that in many cases it's not necessary.
In YAMI, every object has an explicit location, and it's defined by the
domain.
Domain is a group of objects:
What makes one object distinguishable from others, is
the pair (domain_name, object_name). It also means, that
two objects are
considered different, if they have at least one value in this pair
different. It's possible to have objects with the same name if they
exist in different domains.
Object can send a message to any other object.
To do that, object has to provide a name of the destination domain and
a name of the object to which the message is sent.
What makes the message is its name and its parameters.
The message name can be just any string. Messages are not defined
(although it is possible to create an optional layer of static
interfaces on top of this dynamic model) and their names are always
managed dynamically. It means, that there is no constraint on the
message name at run-time.
The parameters that go with a message is a set of values that can have
one of the predefined (primitive) types. The type of the parameter in a
set is also not constrained at run-time. Parameter sets are created for
every message sent.
Both of the above mean that there is nothing like type-safety
of the messages. It's possible to send a message twice with the same
name and with different parameter sets.
Object to which the message is sent can reply with a different
parameter set (which corresponds to the notion of the out
parameters) or can reject the message. Anyway, this information
(return parameters or a rejection message) is sent back and can be
processed by the object which has begun the communication.
Every message is asynchronous from the point of view of the
YAMI model.
It means, that object is not blocked after sending a message - it can
go on uninterrupted and later retrieve the result parameters of the
call or the flags (like after rejection). Of course, this allows to
build a client that will block waiting for the response, but in
its core, YAMI does not require that. Conceptually, the act of sending
a message does not have to map to the invocation of the method
on the receiving object. Such a model is possible, but not required.
In every domain there is one agent.
Agent is a very close equivalent of the CORBA's ORB. It's a piece of
software that is supposed to hide the low-level details of
communication from objects.
Objects request the agent to send a message or to retrieve the return
information from the previous message sent. Objects have to register
themselves with the agent, so that it knows if a message received from
another agent (ie. from another domain) can be delivered to a valid
object.
Agent in fact defines the scope of the domain. If an object is
able to connect to the agent and request him to send a message, it can
be said that this object is in the domain managed by this particular
agent.
This is a little more exact model:
There are three possible types of agents with regard to
their scope of work:
InProc agent
This agent exists in one process together with the objects.
It means, that it is visible to the objects as any other object or
through some function calls (depending on the implementation). The
scope of its domain is the process in which it's created. It means,
that only objects created in the same process can register with it and
send it a request.
It's possible to create more than one agent in the same process (thus,
more than one domain).
Probably this is the simplest agent to implement and use.
OnSite agent
This agent exists on the same computer where the objects
of its domain are located.
The communication between the objects and the agent is a little more
complicated and can be achieved by means of IPC - Inter Process
Communication - (shared memory, pipes, whatever).
Again, it's possible to create more than one agent (and thus more than
one domain) on the same computer.
OffSite agent
The scope of this agent is in theory not limited. If there is a way for
the object to connect to the agent (it may be even separate network
connection), then this object is included in that domain.
Each agent type has its advantages and drawbacks:
InProc agent is limited in its scope and where there are objects
distributed across many processes (even one per process) it's necessary
to create many agents (and many domains).
From the other hand, the InProc agent can take advantage of the fact
that it resides in the same process as its objects and can considerably
speed up message delivery if it discovers that two communicating
objects are in the same domain (so - in the same process) - there is no
need for any network connection nor IPC to deliver the message.
OnSite agent can manage all the objects on one computer and also can
take advantage of IPC if two objects are on the same machine, but this
improvement will not be so big as with the InProc agent.
OffSite agent has the broadest scope, but the communication between him
and objects in its domain is the slowest.
Anyway, it's imperative to state that agents of different types can
coexist in one process or one machine and thus can make a good
compromise if the whole system is well-designed.
Considering the above, the usual steps taken by the object during its
lifetime are:
- create new agent or connect to the existing one (it's
not necessary with the InProc agent)
- register with it (ie. declare the object's name)
- one of (maybe repeatedly):
- request the agent to send a message
- request the agent for the return values from
previous messages
- request the agent for any incoming messages (from
other objects)
- reply to the message received.
- unregister with the agent
- destroy the agent (only if there are no more objects
using this agent)
To make the communication possible, every agent, during its
initialization, has assigned IP address and the port number.
It makes the communication process more explicit (the location of the
domain must be known at the run-time), but at the same time allows to
write very simple implementations. It also means, that agents will
communicate using TCP/IP protocol. It's probably not the fastest
solution (UDP would be at least so fast, but would require
sophisticated protocol so that messages will be delivered reliably and
every implementation would have to comply to this protocol), but surely
one of the simplest to use.
Every agent has to keep the map that will translate domain names to IP
addresses and port numbers. This information can be filled in during
system startup and initialization, but can be changed at run-time.
There is no need for such a strong naming system as in CORBA or COM
(where uniqueness of object names - namely, interface identifiers - is
most important), because name clash could not occur if only domains are
properly registered. So, there is also no problem if in one system
domain and object names will be the same as in other system:
It's possible to write agents so that they will queue requests or just
transform them into usual method invocations on the registered objects.
In the first case, there is a possibility that the object will not
request for incoming messages fast enough (or even not at all). To make
the queue impossible to overflow, agent is allowed to set (but this
should be possible to change from the object's perspective) a limit for
the queue's length or time-out.
This is implementation detail, but YAMI allows messages to be discarded
in case of the time-out and this is one possible situation when this
could happen.
The above model allows to implement very simple (in
comparison with other infrastructures) messaging system. It's important
to say, that this system can be implemented in any language
which libraries support TCP/IP (ie. in any useful language) and
on any platform, which supports this protocol (again, on any useful
platform). This is what can make this idea language- and
platform-independent.
Namely, it should be quite easy to implement appropriate agents in
languages such as C, C++, Java, Tcl or Python for Unix, GNU/Linux and
Windows platforms.
|