Dennis,

That's interesting, and is a reminder to me that I need to study Rio
more.  In your Utilization case, does that allow for arbitrary
server-side decision making?  For example, if a service loses its
connection to a backend database, can it demote itself?  That's an
important use case that led us to service-side elections and relatively
dumb clients.

Chris


-----Original Message-----
From: Dennis Reedy [mailto:[email protected]] 
Sent: Tuesday, February 16, 2010 10:56 AM
To: [email protected]
Subject: Re: Service Wrapper Example

Similar to whats being discussed here is wrapped up in something called
associations in Rio.

Associations are a way to declare that a service uses (has an
association to) another service. Associations define a usage model for
services in and across architectures/deployments. Associations can be
used either at deployment time to assist in how a service get created in
the context of the service(s) it is associated to, or to wire-up
distributed services, injected service references into the declaring
service.

Associations are declared in service deployment configuration, and if
they have been declared with the 'property' attribute, discovered
services will be injected into your service using an IoC approach. Based
on the setter method's signature, the injection type differs.

Given the examples below:

public void setFoos(Iterable<Foo> foos) {
    this.foos = foos;
}

public void setFooAssociation(Association<Foo> foo) {
    this.foo = foo;
}

public void setFoo(Foo foo) {
    this.foo = foo;
}

If the injection point is the the last approach, Rio generates a
client-side proxy and *wraps* discovered associated service instances
with a service selection policy. The service selection strategy provides
a way to determine how services in the collection of discovered services
are invoked. The current service selection strategies are fail-over,
round-robin and utilization (note all service selection strategies will
also prefer local services over remote services).

* The Fail-Over strategy will invoke the first service in it's
collection for each method invocation until that service is no longer
reachable. If the associated service is unavailable, the fail-over
strategy invokes the next service in it's list.

* The Round Robin strategy alternates selection of services from the
association, alternating the selection of associated services using a
round-robin approach.

* The Utilization strategy is a round-robin selector that selects
services running on compute resources whose system resources are not
depleted. System resource depletion is determined by
org.rioproject.system.MeasuredResource provided as part of the
org.rioproject.system.ComputeResourceUtilization object returned as part
of the deployment map. If any of a Cybernode's resources are depleted,
the service hosted in that Cybernode will not be invoked. This is of
particular use in cases where out of memory conditions may occur. Using
the utilization strategy a service running in a memory constrained
Cybernode will not be invoked until the JVM performs garbage collection
and memory is reclaimed. 

Associations can be injected in a lazy or eager mode. Lazy injection is
the default, and injection occurs when a service is discovered. Eager
injection occurs immediately, even if there are no discovered services.

Associations must also deal with proxy failure modes. In a typical
distributed environment, if there are no discovered (available) services
and a remote method invocation is attempted on a service, a
RemoteException is thrown. This seems to make sense, although a better
approach may be in order. Perhaps the dynamic proxy can either wait
until a service is discovered to make the invocation, or provide at
least a retry or timeout. It would seem that the invoking client would
need to do this in any case, and from a coding point of view this
behavior would be in the generated proxy, not in the application code.

The difference here is in a fail-fast approach, service invocation will
fail in an immediate and visible way, allowing the caller to be notified
immediately that something is wrong. In our context here, we would not
immediately raise the RemoteException (at least not right away), we
would go onto the next service. We would fail-fast if there are no
services available. In association terminology, the association would be
broken.

With a fail-safe approach, we would want to constrain the notification
that no services are available (as opposed to failing fast by throwing a
RemoteException) in a managed way having the association proxy retry for
a certain period of time. In this case the fail-safe mode would have the
caller blocking on the service's remote method invocation until a
service becomes available, or until the retry logic exhausts itself. If
the retries are exhausted and there are still no available services, a
RemoteException will be thrown.

Reply via email to