Building isolated components

time to read 4 min | 676 words

In this webcast, I spoke about an architecture where all the different components of the systems are inherently separated and isolated from each other.

Here is a good example of this:

image

The issue is how to implement such a feature. Well, that is actually not the issue. The major issue is how to think about such a feature.

For a start, let us discard the notion that we can have a WhizBang solution for all the components in the system. The behavior for a database down vs. a 3rd party service violating is response time SLA are not something that we can capture in some generic manner. Moreover, the behavior for the login component (backed by the Users table) being problematic vs. the catalog component (backed by Categories, Products, etc tables) being problematic is drastically different.

The common concept that all of those shared, however, is the idea of violating their Service Level Agreements. We can try to capture that concept in order to do one of the following:

  • Raise alert for failed/slow component.
  • Provide alternative implementation for failure scenarios:
    • Capture and queue calls to the components, to be retried at a later date.
    • Reduced functionality in some manner.
  • Allow to manually or automatically restart the component.

We can't provide a generic implementation that would answer all needs, but we can provide a fairly robust infrastructure that will make the implementation easier. That implies interception, so now we need to think about how we can provide an interception hook to our components.

One way of dealing with that is to go with the Erlang model, components are isolated units of execution, which communicate between each other using message passing. We can manage then manage the SLAs using the process itself. The problem with this is that for most of the scenarios, we usually want to have a request/response semantic (imagine a request to get the train schedule from a particular city). Message passing in this case is not an easy solution, mostly because of thread management issues that simple does not exist in Erlang (different VMs).

This is still my favorite concept, and I keep trying to think about good ways of combining the notion of message passing and request/response. Most of those idea involve some concept about thread yielding for the target process, but then we run into request handling threads starvation and thread affinity and thread safety issues. In general, if this is complex, it is a good indication that it is a bad idea.

Another solution, which fit the way we handle things on the CLR much more is by proxying the component and handling much of that behavior there. The idea that I had was something like this:

image

The component proxy is responsible for managing the SLA ( timing, errors, etc) and can notify the SLA behaviors when they go out of line. The SLA behavior can decide to move to an alternate implementation or to just shut the component down (obviously raising alerts and such).

An additional system will allow us to restore the component to the default implementation, or manually move it to the alternative implementation in preparation of some event that is about to occur.

This is the idea of a Circuit Breaker from Release It on a large level.

From the point of view of the code, we are talking about something like this:

public interface IOrderService
{
	// ...
}

// backed by a database
public class DefaultOrderService : IOrderService
{
	// ...
}

// use a cache populated by the default order service
// during normal operation
public class CachingOrderService : IOrderService
{
	// ...
}

// behavior is all in the base class
public class OrderServiceSlaBehavior : AlternativeImplementationOf<DefaultOrderService>.Is<CachingOrderService>
{
}

With the appropriate facility, this should be seamless. Thoughts?

To the nitpickers, yes, I am aware that this looks a lot like SOA.