Click here to Skip to main content
13,548,896 members
Click here to Skip to main content
Add your own
alternative version

Tagged as


47 bookmarked
Posted 22 Jan 2012
Licenced CPOL

How to Implement Load Balancing to Distribute Workload

, 22 Jan 2012
Rate this:
Please Sign up or sign in to vote.
Simple example showing how to implement the load balancing if you need to increase the performance by distributing the workload across multiple services.


The example demonstrates a communication scenario where the capacity of one running service is not enough and you want to increase the performance by distributing the workload across multiple services. To simulate the scenario, the example below implements a client application using a service to calculate π (PI) number. The calculation is split into many small intervals (400 in our example). Therefore, the service gets overloaded and the performance drops down.

The solution for such scenarios could be using of load balancer. The load balancer is a component maintaining a farm of services (typically same services but running on different machines) and is exposed to receive messages instead of the real service. The client does not know about this setup and thinks it communicates directly with the service. When the client sends a request, the load balancer receives this message and forwards it to the service picked from the farm. The service processes the message and sends back the response that is routed via the load balancer back to the client.

To run the example bellow you must execute applications in the following order:
1. PiCalculator up to 3 instances.
2. LoadBalancer
3. Client

The example bellow uses Eneter Messaging Framework that provides functionality for various communication scenarios. (The framework is free and can be downloaded from More detailed technical info can be found at



The client is a simple application containing a button sending the request to the service to calculate π (PI) number. The calculation is split into many small intervals. Therefore, the client sends about 400 messages each containing a small interval for the calculation. Then it collects all responses and summarizes them together to get the final result, the PI number.

using System;
using System.Windows.Forms;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;

namespace Client
    public partial class Form1 : Form
        // Requested calculation range.
        public class Range
            public double From;
            public double To;

        public Form1()

        public void OpenConnection()
            // Create TCP messaging for the communication.
            // Note: Requests are sent to the balancer that will forward them
            //       to available services.
            IMessagingSystemFactory myMessaging
                = new TcpMessagingSystemFactory();
            IDuplexOutputChannel anOutputChannel
                = myMessaging.CreateDuplexOutputChannel("tcp://");

            // Create sender to send requests.
            IDuplexTypedMessagesFactory aSenderFactory
                = new DuplexTypedMessagesFactory();
            mySender = aSenderFactory.CreateDuplexTypedMessageSender<double, Range>();

            // Subscribe to receive response messages.
            mySender.ResponseReceived += OnResponseReceived;

            // Attach the output channel and be able to send messages and receive responses.

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
            // Detach the output channel and stop listening for responses.

        private void CalculatePiBtn_Click(object sender, EventArgs e)
            myCalculatedPi = 0.0;

            // Split calculation of PI to 400 ranges and sends them for the calculation.
            for (double i = -1.0; i <= 1.0; i += 0.005)
                Range anInterval = new Range() { From = i, To = i + 0.005 };

        private void OnResponseReceived(object sender, TypedResponseReceivedEventArgs<double> e)
            // Receive responses (calculations for ranges) and calculate PI.
            myCalculatedPi += e.ResponseMessage;

            // Display the number.
            // Note: The UI control can be used only from the UI thread.
            InvokeInUIThread(() => ResultTextBox.Text = myCalculatedPi.ToString());

        // Helper method to invoke some functionality in UI thread.
        private void InvokeInUIThread(Action uiMethod)
            // If we are not in the UI thread then we must synchronize via the invoke mechanism.
            if (InvokeRequired)

        private IDuplexTypedMessageSender<double, Range> mySender;
        private double myCalculatedPi;

Load Balancer

The load balancer is a simple console application acting as a real service. In this example it has a farm of three services. (To keep things simple, all three services run on the same computer. They listens to different ports.) When a user presses the button in the client application, the load balancer receives about 400 request messages and distributes them to its three services from the farm. To decide which service is picked from the farm, the load balancer uses Round-Robin algorithm. Therefore, all services are chosen evenly. (The Round-Robin algorithm is suitable for load balancing if processing of requests takes approximately same time.) The code is very simple. The whole implementation is here:

using System;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.Messaging.Nodes.LoadBalancer;

namespace LoadBalancer
    class Program
        static void Main(string[] args)
            // Create TCP messaging for the communication with the client
            // and with services performing requests.
            IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();

            // Create load balancer.
            // It receives requests from the client and forwards them to available services
            // to balance the workload.
            ILoadBalancerFactory aLoadBalancerFactory
                = new RoundRobinBalancerFactory(aMessaging);
            ILoadBalancer aLoadBalancer
                = aLoadBalancerFactory.CreateLoadBalancer();

            // Addresses of available services.
            string[] anAvailableServices = {
                       "tcp://", "tcp://", "tcp://" };

            // Add IP addresses of services to the load balancer.
            foreach (string anIpAddress in anAvailableServices)

            // Create input channel that will listen to requests from clients.
            IDuplexInputChannel anInputChannel
                = aMessaging.CreateDuplexInputChannel("tcp://");

            // Attach the input channel to the load balancer and start listening.

            Console.WriteLine("Load Balancer is running.\r\nPress ENTER to stop.");

            // Stop lisening.

PI Calculator

The calculator is a simple service (console application). It receives requests to perform calculations for specific intervals. When the calculation is done, it sends back the calculation result.

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;

namespace PiCalculator
    // Requested calculation range.
    public class Range
        public double From;
        public double To;

    class Program
        static void Main(string[] args)
            string aServiceAddress = GetMyAddress();
            if (aServiceAddress == "")
                Console.WriteLine("The service could not start because all possible ports are occupied.");

            // Create TCP messaging for receiving requests.
            IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
            IDuplexInputChannel anInputChannel = aMessaging.CreateDuplexInputChannel(aServiceAddress);

            // Create typed message receiver to receive requests.
            // It receives request messages of type Range and sends back
            // response messages of type double.
            IDuplexTypedMessagesFactory aReceiverFactory = new DuplexTypedMessagesFactory();
            IDuplexTypedMessageReceiver<double, Range> aReceiver
                = aReceiverFactory.CreateDuplexTypedMessageReceiver<double, Range>();

            // Subscribre to messages.
            aReceiver.MessageReceived += OnMessageReceived;

            // Attach the input channel and start listening.

            Console.WriteLine("Root Square Calculator listening to " + aServiceAddress +
                " is running.\r\n Press ENTER to stop.");

            // Detach the input channel and stop listening.

        private static void OnMessageReceived(object sender, TypedRequestReceivedEventArgs<Range> e)
            Console.WriteLine("Calculate From: {0} To: {1}", e.RequestMessage.From, e.RequestMessage.To);

            // Calculate requested range.
            double aResult = 0.0;
            double aDx = 0.000000001;
            for (double x = e.RequestMessage.From; x < e.RequestMessage.To; x += aDx)
                aResult += 2 * Math.Sqrt(1 - x * x) * aDx;

            // Response back the result.
            IDuplexTypedMessageReceiver<double, Range> aReceiver
                = (IDuplexTypedMessageReceiver<double, Range>)sender;
            aReceiver.SendResponseMessage(e.ResponseReceiverId, aResult);

        // Helper method to get the address.
        // Note: Since our example services are running on the same machine,
        //       we must ensure they do not try to listen to the same IP address.
        private static string GetMyAddress()
            List<int> aPossiblePorts = new List<int>(new int[]{ 8071, 8072, 8073 });

            // When we execute this service three time we want to get three instances
            // listening to different port.
            IPGlobalProperties anIpGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
            IPEndPoint[] aTcpListeners = anIpGlobalProperties.GetActiveTcpListeners();

            // Remove from the possible ports those which are used.
            foreach (IPEndPoint aListener in aTcpListeners)

            // Get the first available port.
            if (aPossiblePorts.Count > 0)
                return "tcp://" + aPossiblePorts[0] + "/";

            // All three instances are used.
            return "";


And here are all applications communicating together.



This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Slovakia Slovakia
My programming path started in 1987 when I got my first computer Sharp MZ-800.
It came with 8 bit CPU Z80, 64Kb RAM and the tape recorder. It was a great machine. I think I still have it somewhere.
I was fascinated and I started to write first programs. Eventually I became developer and software architect. I like innovations and clean nice solutions.

You may also be interested in...


Comments and Discussions

GeneralMy vote of 5 Pin
kyuka isaac17-Apr-13 22:46
memberkyuka isaac17-Apr-13 22:46 
Questionconfused Pin
Avinash Morris28-Mar-13 23:49
memberAvinash Morris28-Mar-13 23:49 
AnswerRe: confused Pin
Ondrej_Uzovic29-Mar-13 0:37
memberOndrej_Uzovic29-Mar-13 0:37 
GeneralRe: confused Pin
Avinash Morris4-Apr-13 8:49
memberAvinash Morris4-Apr-13 8:49 
GeneralMy vote of 3 Pin
Avinash Morris28-Mar-13 23:47
memberAvinash Morris28-Mar-13 23:47 
QuestionThe load balancer continue to send requests to detached services? Pin
television_pham11-Nov-12 15:34
membertelevision_pham11-Nov-12 15:34 
AnswerRe: The load balancer continue to send requests to detached services? Pin
Ondrej_Uzovic13-Nov-12 21:26
memberOndrej_Uzovic13-Nov-12 21:26 
GeneralRe: The load balancer continue to send requests to detached services? Pin
television_pham21-Nov-12 16:59
membertelevision_pham21-Nov-12 16:59 
Thank you very much for you answer!!!
QuestionYour words about Eneter vs. MSMQ?? Pin
Fidel Orozco Gómez7-Feb-12 13:54
memberFidel Orozco Gómez7-Feb-12 13:54 
AnswerRe: Your words about Eneter vs. MSMQ?? Pin
Ondrej_Uzovic8-Jul-12 10:04
memberOndrej_Uzovic8-Jul-12 10:04 
GeneralMy vote of 5 Pin
moragos27-Jan-12 8:27
membermoragos27-Jan-12 8:27 
GeneralMy vote of 5 Pin
johannesnestler22-Jan-12 22:31
memberjohannesnestler22-Jan-12 22:31 
GeneralMy vote of 5 Pin
pothiq22-Jan-12 16:24
memberpothiq22-Jan-12 16:24 
GeneralMy vote of 5 Pin
Filip D'haene22-Jan-12 11:20
memberFilip D'haene22-Jan-12 11:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.180515.1 | Last Updated 22 Jan 2012
Article Copyright 2012 by Ondrej_Uzovic
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid