Things to Consider When Implementing a Load Balancer with WCF
Applies to: Windows Communication Foundation
Published: June 2011
Author: Bill Collette
This topic contains the following sections.
As distributed systems become more complex, the challenges of architecting a WCF system become greater. There are many issues to consider. A few of them are how to distribute network traffic, how to balance the server load, how to provide fault tolerance, and how to implement security.
When many clients connect, the loads that are placed on WCF services increase. An important question is how to handle those times when the demand is heavy. A common approach is to implement a load balancer within the infrastructure. A load balancer takes incoming requests and distributes them among a number of servers that run the same service. A load balancer keeps a specific server from being overwhelmed with requests, which can significantly reduce the performance of the WCF service.
When you implement a load balancer for WCF services, think about how to configure your bindings. Points to consider are:
Should you use sticky or non-sticky sessions?
What are the performance considerations?
What are the security considerations?
This article discusses the different bindings you can use to load balance a WCF service. It uses several scenarios that demonstrate the effect of each of them.
The purpose of a load balancer is to disperse traffic equally among several servers. The goal is to reduce the load on each server and continue to provide acceptable performance during periods of increased activity.
The following illustration shows a commonly used implementation of a load balancer within an enterprise. The load balancer, whether it is a hardware appliance or the Windows Network Load Balancing Service (WNLBS), is within the firewall and sits between the external services and the company’s internal core services.
In this example, the external services are services that accept connections from clients on the web. The external services are on several servers, and interact with the core services. The core services connect to the company’s internal databases in order to update and retrieve customer data, to process payments, to update inventory, and to initiate shipments. The load balancer that sits between the external and core services ensures that response times are acceptable. It monitors the load of each server and distributes the requests from the external services to the internal server(s) that are the least busy at that moment.
It is just as important to ensure that a load-balanced WCF environment uses the proper binding as to implement the proper infrastructure. There are several binding options available for load balancing. See "Load Balancing" on MSDN at http://msdn.microsoft.com/en-us/library/ms730128.aspx for a complete list of these bindings.
This article discusses three binding options that are suitable for a load-balanced environment. They are BasicHttpBinding, WSHttpBinding, and NetTcpBinding.
The BasicHttpBinding is simple to implement, and works very well with existing HTTP load balancing techniques because the traffic is no different than other common types of web traffic. However, to avoid server affinity, you should disable the Keep-Alive value. To do this, implement a custom binding that sets the KeepAliveEnabled property to false. The MSDN topic “Load Balancing” mentioned previously, shows you how to configure the custom binding with KeepAliveEnabled specified.
The WSHttpBinding provides a variety of security options. For example, the scenario shown in the previous illustration successfully distributes network traffic across several servers, and provides some fault tolerance if a server goes down. However, it does not secure the data as it is transported between the external and core Services.
If you require secure sessions, one option is the WSHttpBinding. This binding provides transport security that protects the data as it travels between the external and core services, yet still maintains an acceptable level of performance. (In this scenario, acceptable performance is defined as sub-second response times, with the ability to handle a throughput of 100 requests per second, or more.) Transport security uses HTTPS to protect the data that is sent over the line. HTTPS prevents rogue users or programs within the network from reading the data.
The following illustration shows a scenario that uses transport security.
The WSHttpBinding also allows the load balancer to effectively route traffic to the core services.
The following XML code is an example of how to configure the WSHttpBinding so that it provides transport security.
<bindings> <wsHttpBinding> <binding name="MyServiceBinding"> <security mode="Transport"> <transport clientCredentialType="None" ></transport> </security> </binding> </wsHttpBinding> </bindings>
Establishing Security Context
The previous example showed how to implement transport security. You can also provide security at the message level by:
Enabling sticky sessions or
Setting the establishSecurityContext property to false.
Enabling sticky sessions is beyond the scope of this article. Most hardware and software load balancers have this feature. Once a client establishes a session to the server, a sticky session will ensure subsequent requests from the client will route to the same server every time. This is often referred to as server affinity. If you are using Windows Server 2008, you have the option to user the Network Load Balancing feature. For more information refer to http://technet.microsoft.com/en-us/library/cc732855(WS.10).aspx.
The following illustration shows a scenario that uses message security.
In this scenario, sticky sessions must be enabled on the load balancer. Enabling sticky sessions prevents errors that can occur when the system is under high load.
If sticky sessions are not enabled, and the establishSecurityContext property of the WSHttpBinding is set to true or it is not specified, it is possible to receive a System.ServiceModel.FaultException. This error means that the security context token is either expired or is invalid, and the message was not processed. When a security session is established between servers, there is a one-time initial step that exchanges asymmetrically encrypted messages. Subsequent requests use this established session and messages are symmetrically encrypted. It is possible that one of these subsequent requests is routed to a server that is not a part of the established session. This causes a FaultException to occur. If the establishSecurityContext property is set to false, the one-time initial step is not executed, and requests do not rely on an established session. This is the alternative to using sticky sessions. The following XML code shows how to set the establishSecurityContext property to false.
<bindings> <wsHttpBinding> <binding name=”MyServiceBinding”> <security mode=”Message” > <message establishSecurityContext=”false” clientCredentialType=”Windows” /> </security> </binding> </wsHttpBinding> </bindings>
How the establishSecurityContext property is set impacts performance. To determine how to configure this property, you must first understand how the client invokes the service. If the client invokes the service and then disconnects, performance is better with establishSecurityContext set to false because symmetric encryption is much faster than asymmetric encryption. On the other hand, if the client invokes the service and calls several methods, performance is better with establishSecurityContext set to true.
The NetTcpBinding provides better performance than either BasicHttpBinding or WSHttpBinding do. However, load balancing is more challenging to implement because the NetTcpBinding pools TCP connections by default. This binding ensures that clients remain sticky to the same server.
You can use the NetTcpBinding in the same scenario that used WSHttpBinding, if you implement it with a few changes. Because clients have affinity to the server associated with their channel, application code should include try-again logic in case the server fails. This logic ensures that the client is routed to a server that is up and responsive.
Although this article is not a comprehensive review of every issue to consider when you use a load balancer with WCF, it does present some real-world architectural challenges. When you choose a binding, think about sticky sessions, performance, and security considerations. Production scenarios vary, but they often require you to have one or more load balancers. Take this into account as you design your service-oriented architecture.
For more information, see the following resource:
Load Balancing - http://msdn.microsoft.com/en-us/library/ms730128.aspx