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.

On Feb 16, 2010, at 1126AM, Christopher Dolan wrote:

> Tom's technique below is nice for automatic failover.  Just for a point
> of reference, I'll describe the hot-standby approach we've taken at
> Avid.
> 
> * Declare that your IFooService is an IRedundantService
> * The IFooService instances in the group discover each other and hold
> an election
> * The winner calls joinMgr.modifyAttributes() to mark itself as primary
> * The IFooService instances ping each other and if any one stops
> responding, another election is triggered
> * Clients search for the IFooService that is marked primary=true and
> talk only to it
> 
> Limitations of this approach:
> * need for IFooService instances to inter-communicate
> * moments during election when there is no primary
> * rare partial-disconnect conditions where you get two primaries
> 
> Wins of this approach:
> * election protocol is entirely up to the IFooServices, no client logic
> except to trust the Entry that says primary=true
> * only one primary at a time
> * the IFooService instances are already in contact, so adding state
> synchronization requires little extra infrastructure
> 
> Good-and-bad aspects:
> * clients can decide how to handle the no-primary case themselves.
> More code, but more control too.
> 
> 
> I'd love to hear comments/criticisms of our approach, and if anyone has
> implemented something similar.
> 
> Chris
> 
> -----Original Message-----
> From: Tom Hobbs [mailto:[email protected]] 
> Sent: Tuesday, February 09, 2010 4:21 AM
> To: [email protected]
> Subject: Service Wrapper Example
> 
> Hi,
> 
> I mentioned in another thread that I had come across code which provides
> service fail over and auto-rediscovery.  I've posted details of the kind
> of
> code that was used to (note this has been reinvented in my head just now
> and
> only loosely tested);
> 
> http://wiki.apache.org/river/AutomaticServiceReplacement
> 
> I hope that someone finds it useful and/or interesting.
> 
> It's important to note that in the interests of simplicity the
> ServiceWrapper class in the article is explicitly linked to the dummy
> service described.  Obviously using more reflection magic it's possible
> to
> remove this linkage so that ServiceWrapper can wrap any service you like
> and
> it's invoke method would invoke the method supplied to it, rather than
> the
> only method available in the dummy article.
> 
> Thanks to Jukka for his Wiki account suggestion.
> 
> Enjoy,
> 
> Tom

Reply via email to