Home Products Download Events Support Registration

Home
Up

HTTP Dynamic Load Balancing Using SocketPro

support@udaparts.com
05/16/2009

Contents

1.    Introduction

        When a large company has a web site with many features implemented, the site is usually heavy loaded by many people over world. One particular problem is that web site is often very slow to response to a request from a web browser. This is normal even for many well known companies. To solve this problem, load balancers are used. Typically people use hardware as man-in-middle to distribute web requests onto a set of real HTTP servers to process in parallel so that response time is reduced and through put is increased to make users happy.

        However, hardware approach is simple but it has its own drawbacks in comparison to other approaches. We'll not compare hardware approach with others, but will focus comparison between hardware approach with load balancing by our SocketPro.

        SocketPro is written with batching requests and processing them in parallel by non-blocking socket communication from the very beginning. On client side, SocketPro comes with an ATL/COM object USocketPool, the foundation for UDAParts load balancing. The following sites are useful for you to further study the object.

        a.    ASP.NET 2 Async Pages with SocketPro
        b.    Extend SocketPro load balancing to serve your purposes
        c.    Scientific and engineering parallel computing across many machines with load balancing and disaster recovery

2.    This sample scenario

        The web server application runs with a central load balancer, which is connected with a set of real servers, A, B, C and D. Communication between the central and real servers is binary instead of text-based HTTP. Most of business processing is completed on real servers.

       

        However, load balancer may be used for logging transaction data into a central store (memory, file, or database). Also, the balancer may have its own memory cache implemented. Further, the load balancer may access other servers for other business requirements, which are not shown in the above figure. Because this is a common business web application, many transactions can be partitioned into a small number of different types of jobs, which can be distributed onto real servers to process concurrently. At the end, the central balancer collects results from these real servers.

3.    Partition and execute jobs

        The sample project is located at the directory C:\Program Files\UDAParts\SocketPro\samples\HTTPLoadingBalance\csharp (vbnet) for both C# and vb.NET.

        To take advantage of parallel computing. First, we need to partition a large and complicate task into a set of small and simple jobs. Take this sample as an example. We partition the following web tasks into three jobs, which are three SQL statements for three data tables. The source data may come from three different databases through three real servers.
             

        protected void btnExecute_Click(object sender, EventArgs e)

        {

                if (!StartLB()) //Start load balancer

                        return;

                List<string> lstSQL = new List<string>();

                lstSQL.Add(txtSQL1.Text);

                lstSQL.Add(txtSQL2.Text);

                lstSQL.Add(txtSQL3.Text);

                IList<DataTable> tables = m_lbRAdo.PrepareAndExecuteJobs(lstSQL);

                gvSQL1.DataSource = tables[0];

                gvSQL2.DataSource = tables[1];

                gvSQL3.DataSource = tables[2];

                gvSQL1.DataBind();

                gvSQL2.DataBind();

                gvSQL3.DataBind();

        }

        At the end, bind three data tables onto three data grid view controls after calling the method PrepareAndExecuteJobs.

        Now, let's look at the code snippet of the method PrepareAndExecuteJobs.
        

        public IList<DataTable> PrepareAndExecuteJobs(List<string> lstSQL)

        {

                if(lstSQL == null || lstSQL.Count == 0)

                        throw new InvalidOperationException("Must pass in a list of SQL statements");

 

                 //lock an identity for an async handler

               CRAdo handler = (CRAdo)JobManager.LockIdentity();

                if(handler == null)

                        throw new InvalidOperationException("ADO loading balance is down");

                

                //set a sorted list (job identification number <==> data table)

                handler.m_JobTable = new SortedList<long, DataTable>();

                

                foreach (string strSQL in lstSQL)

                        //prepare and execute jobs automatically through async handler, and each of them contains one task (request) only

                        handler.GetDataReaderAsyn(strSQL);

 

                //wait until all of jobs with this identity are completed.

                JobManager.Wait(handler);

 

                IList<DataTable> tables = handler.m_JobTable.Values;

 

                //release identity back to pool for reuse

                JobManager.UnlockIdentity(handler);

                return tables;

        }

        At the beginning, we lock an identity for an asynchronous ADO.NET handler. Afterwards, we prepare a set of jobs, and each of jobs contains one SQL statement for a data table. Next, we'll wait until all of jobs are processed and returned from different real servers.

        At the end, we sort returned data tables according to job identification numbers so that a list of original SQL statements correctly correspond to the list of data tables. Finally, we release the previously locked identity back to pool for reuse.

4.    Gather returned results

        We have talked about how to create jobs from a large and complicate web request by partitioning. Now we need to know how to gather results from different real servers.

        First of all, we should make sure how to process one result from one real server. This is simple as long as you go through the tutorial one. This sample is slightly more difficult because you'll reuse existing class CAsyncAdoHandler inside SocketProAdapter. However, this is still simple as long as you read through this article and look at the attached sample at the directory. 

        To gather returned results from different real servers, you need to override either virtual function OnReturnedResultProcessed or OnJobDone. For this sample, we override the later one as shown in the below.
        

        protected override void OnJobDone(CRAdo Handler, IJobContext JobContext)

        {

                CRAdo RAdo = (CRAdo)JobContext.Identity;

                lock (m_cs)

                {

                        RAdo.m_JobTable[JobContext.JobId] = Handler.ReturnTable;

                }

        }

        There are two pitfalls here. First, it is mandatory that we should synchronize the dictionary object because the object may be accessed from different threads at the same time. The second is that the reference of job context identity (RAdo) is not necessarily equal to the reference Handler. However, the reference Handler must contain a data table if available, which must belong to the job context. As described at this article, requests and their returning results are processed separately by different handlers. Once knowing the above two pitfalls, you are expected to understand the above code snippet.

5.    Load balancing comparison between software and hardware

        Now, let's compare hardware load balancing with SocketPro approach. SocketPro approach has following list of advantages over hardware load balancing.

  • SocketPro approach is much cheaper. Hardware load balancer usually costs between $3000 and $50,000 each. If your system will be distributed onto many different companies. You may have to consider this fee.
  • SocketPro approach is very extensible with your business logics and requirements you like. This is impossible to hardware load balancers. If you luckily find such a hardware load balancer, it may be extremely expensive for you to afford.
  • SocketPro approach can have zero configuring settings. Settings are complicate at beginning for hardware load balancing. You may hire engineers to support your customers. This may be a burden to your company. If you use SocketPro, there is no such a problem at all. You can remove configuring settings to zero by software programming with your own logics.
  • SocketPro may be faster because data communication between balancer and real servers are more effective in binary. This is not possible with hardware approach. We can strategically distribute only required key data in binary from the central load balancer onto real servers through software. Also we can limited returning results in binary so that unwanted data can be filtered away.
6.    Further readings