Sunday, April 26, 2009

Using NLB for low budget load-balancing



In a project I worked on a couple of years ago I used NLB to experiment & prove the stateless-ness of the architecture I planned.
NLB is a service that comes with windows servers, it allows to load balance application for better availability.
I'm a fan of hardware load balancing myself, more reliable, dedicated machine for this important task and all sort of programmatic traffic manipulation, but...I realized this information could be useful for lower budget projects....so...here it is.

The Basics

I built the the experiment on two windows 2003 machines, one of them worked as the NLB itself
and application server (machine name "asavasrv01") and the 2nd machine as application machine (machine name "pensionsrv2").
In a real project if you have an old machine that can not perform as an application server you can always use it as the load balancer.
The sample application is win Form client and web service as server.


Setting the NLB cluster

1st step is adding NLB provider to network adapter.



2nd step - set NLB manager for multi cast and add each server to the server list of the NLB manager.




3rd and final step set the load (usually equally for each server, in this case 50%-50%...).



If you set everything your result should be look something like this:



Testing load-balancing

I built the simplest web service returning kinda "hello world" message but with a little tweak - the server name.

The client calls the VIP or cluster name given earlier, we can see the calls are divided between both servers:



Testing Availability

I unplugged one of the server from network to simulate server failure.
we can see the result in the NLB Manager:



On client side, since it calls the server in a loop we experience a failure of a few calls, but after 2-3 seconds the application recovered.

We can see the NLB detected the server failure and passed the load to one server.



Conclusions

After a short setup we saw how the NLB balances the load between the servers and how it detects server failure and keeps the application available!

but...

NLB can not (like other solutions...) detect application failure and does not analyze any server parameters for best performance and availability (and...and..)
it divides the network load between two or more servers in a round-robin order.
Hardly the best load balancing solution, but hey! it's free! if you don't have a budget for a fancy load-balancer solution, you can at least keep your application server more reliable & available.

Think about it!
Diego

Monday, April 13, 2009

AOP – Aspect Orient Programming in .NET

What is AOP?

All methodologies have always searched for a way to make code more readable & maintainable.
Procedural programming splitted our code to procedures and OOP divided our world to entities with "responsibility" to their internal data and operations.
AOP is not a replacement... it tries to give an elegant add-on to those infrastructure parts that are cross modules and/or cross layers of any enterprise application.

AOP in .net?

In .net framework the key to AOP implementation is - interception.
This concept is mostly known to programmers who wrote applications using multi-threading, remoting, enterprise services (COM+) and of course - WCF.
Interception wraps and seperates our objects within a separate context.
This same method allows programmers to define with a simple attribute - transactional behaviour ([Transaction=Required]), thread synchronization ([Synchronization]), check authorization against an Active-Directory ([PrincipalPermission(SecurityAction.Demand, Role = "Administrators")] etc etc.

What is it good for?

In a recent project I worked on we were requested to address a very strict regulation with a focus on auditing, authorization and exception management.
Using an infrastructure built using AOP principals we managed to handle these three and some more in a single layer - forcing a policy across the entire application with no dependency on the 'user' (the programmer in this case) and fully separated from the logical code of the application.
Other uses for this could be performance profiling, session management, in fact - any cross-application policy you wish to implement.
When needed you can always be more flexible and expose some attributes to allow the 'user' to configure the behaviour of this policy - but - the code remains separated and elegantly wrapped.

How to implement?

To implement this you need to inherit ContextBoundObject - this will 'make' our object to be separated in it's own private context.


[Intercept]
public class ServiceInterfaceBase : ContextBoundObject


This will cause all calls to our object to become messages (IMessage), this way - when implementing an IMessageSink we could intervene and 'canalize' all the calls to this object (and it's ancestors) to pass through our interception layer - there we can check authorization, write to a log, handle exceptions etc etc.

Our own "Interception" attribute to help us mark our base class and attach our property to the new context:


[AttributeUsage(AttributeTargets.Class)]
public class InterceptAttribute:ContextAttribute
{
public InterceptAttribute() : base("InterceptAttribute") { }

public override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
{
//add our intercept property to context!!
IContextProperty interceptProperty = new InterceptProperty();
ctorMsg.ContextProperties.Add(interceptProperty);
}

//Called by the runtime in the creating client's context
public override bool IsContextOK(Context ctx, IConstructionCallMessage ctorMsg)
{
if (ctx.GetProperty("Interception") == null)
{
return false;
}

return true;
}
}


Here you can see the context property, here we'll make sure the "message" sent to our custom "sink":


public class InterceptProperty : IContextProperty, IContributeServerContextSink
{
#region IContextProperty Members

public void Freeze(Context newContext)
{
}

public bool IsNewContextOK(Context newCtx)
{
InterceptProperty newContextProperty = newCtx.GetProperty("Interception") as InterceptProperty;

if (newContextProperty == null)
{
Debug.Assert(false);
return false;
}

return true;
}

#region IContributeServerContextSink Members

public IMessageSink GetServerContextSink(IMessageSink nextSink)
{
//send calls to our custom sink!!!
IMessageSink interceptSink = new InterceptSink(nextSink);
return interceptSink;
}

#endregion

#end region
}


All calls to our application will pass through "HandleMessage" method, there you can log every call, every result, handle exceptions, check authorization for all calls and prevent them when needed, profile methods and every crazy idea or policy you wish to centralized in one place.


public class InterceptSink : IMessageSink
{
private IMessageSink m_NextSink;
private readonly object syncRoot = new object();

public InterceptSink(IMessageSink nextSink)
{
lock (syncRoot)
{
m_NextSink = nextSink;
}
}

#region IMessageSink Members

public IMessage SyncProcessMessage(IMessage msg)
{
IMethodReturnMessage returnedMessage;

HandleMessage(msg, false, out returnedMessage);

return returnedMessage;
}

public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
{
IMethodReturnMessage returnedMessage;

HandleMessage(msg, true, out returnedMessage);

return m_NextSink.AsyncProcessMessage(msg, replySink);
}

public IMessageSink NextSink
{
get { return m_NextSink; }
}

private void HandleMessage(IMessage msg, bool IsAsync, out IMethodReturnMessage returnedMessage)
{
IMethodMessage methodMessage = (IMethodMessage)msg;
returnedMessage = null;

if (!IsAsync)
{
returnedMessage = (IMethodReturnMessage)m_NextSink.SyncProcessMessage(msg);

//read exception and do something about it? log?
exceptionName = GetExceptionName(returnedMessage);
exceptionMessage = GetExceptionMessage(returnedMessage);
exceptionTrace = GetExceptionTrace(returnedMessage);

//profile...?
TimeSpan exeTimeTimeSpan = DateTime.Now.Subtract(beginTime);
exeTime = exeTimeTimeSpan.TotalMilliseconds;
}
else
{
returnedMessage = null;
exceptionName = "Not Available";
exceptionMessage = "Method invoked asynchronously";
exceptionTrace = "Not Available";
}
}

#endregion
}


That's it!

Hope this code will be helpfull, do comment if so!!

Good luck.
Diego

recommended source: Programming .NET Components, Juval Lowy.