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.
