Production Configuration Settings

Applies to: Windows Communication Foundation

Published: June 2011

Author: Robert Dizon

Referenced Image

This topic contains the following sections.

  • Optimal Settings for Performance and Scalability
  • Conclusion
  • Additional Resources

Optimal Settings for Performance and Scalability

This section is a compilation of optimal configuration settings and fixes for performance and scalability issues. Apply and test these fixes during development, before you use them in production. You can consider these groups of related configuration settings as a reference that you can use to fine-tune WCF solutions that are deployed in enterprise-level integration scenarios.

The configuration settings are grouped by hop. Refer to the three-tier architecture illustration to identify where the hops are in the overall scenario.

From Hop 1 – WCF Client or User-facing Web Application (Node 1) and IIS hosting (Node 2):

Microsoft provides extensive configuration guidelines for WCF client and IIS application server. See the following links:

From Hop 2 (Node 3) – WCF Service Configuration Settings:

Microsoft provides extensive configuration guidelines for WCF performance and scalability. See the following links:

From Hop 3 (Node 4) – Data Access or WCF Optimization Code:

There is a useful discussion with procedures on optimizing the data access layer at this link: http://www.linkedin.com/answers/technology/software-development/TCH_SFT/416855-13606449

The following section includes more possible code fixes to help you to optimize performance and scalability. However, these fixes are more time-consuming than the ones in the previous section. They may require more development time or that you refactor your existing code. Use these fixes only if you have tried all the recommended configuration settings and found none of them to work.

Recommended Code Modifications:

  1. Use asynchronous client-side invocations. For more information, see "Summarizing Client Side Asynchronous Invocations in WCF/WCF Silverlight" at http://www.codeproject.com/KB/silverlight/AsyncCallsWCFSilverlight.aspx.

  2. See "Implement a Custom HTTP Handler" on MSDN at https://msdn.microsoft.com/en-us/library/ms228090.aspx

  3. See "Creating an Asynchronous HTTP Handler" on MSDN at https://msdn.microsoft.com/en-us/library/ms227433.aspx.

  4. Improve the performance of the data access layer by applying the following guidelines:

    1. Change from Integrated Windows Authentication to SQL Server authentication. This allows you to use a simple user name and password that are stored in a trusted database. The performance overhead for Integrated Windows Authentication is high.

    2. If the number of inbound and outbound messages is very large, you can implement paging in the WCF service layer, in both the client request and the WCF response. Paging is a technique that uses fewer messages. (Each message contains more data.) Paging reduces the number of round trips required between the client and the server. The following code demonstrates how to use paging.

Service-Consuming Client Side Paging

C# Code Version

public List<Item> GetItemsByTypeAndAccountNumber(int typeID, string strAccountNumber)
{
        try
        {
            // Set the maximum pages possibly align with grid user interface
            int iResultsPerPage = MaxPaging; 
            bool bCompleteFlag = true;
            int iPageCounter = 1;
            List<Item> tempList = new List<Item>();

            if (typeID == 1)
            // Get all records narrow down by account number
List<Item> retList = WCFServiceReference.GetAllRecords(accountNumber, iPageCounter, iResultsPerPage, out bCompleteFlag).ToList<Item>();
            else
            List<Item> retList = WCFServiceReference.GetAllRecords(iPageCounter, iResultsPerPage, out bCompleteFlag).ToList<Item>();

            if (retList != null)
            {
                  // We got results, but we need to check and see if there are more results
                  while (!bCompletFlag)
                  {
                      // try getting the next page
                      iPageCounter ++;
         if (typeID == 1)
    tempList = WCFServiceReference.GetAllRecords(accountNumber, iPageCounter, iResultsPerPage, out bCompleteFlag).ToList<Item>();
                else
                    tempList = _ WCFServiceReference.GetAllRecords(iPageCounter, iResultsPerPage, out bCompleteFlag).ToList<Item>();
                         
                      // add it to the main list
                      foreach (Item i in tempList)
                      {
                          retList.Add(i);
                      }
                      // clear the temp list
                      tempList.Clear();
                  }
             }
             return retList;
        }
        catch (Exception ex)
        {
             HandleException();
             throw new Exception("Error getting records from the service layer: " + ex.Message, ex);
        }            
}

VB.NET Code Version

Friend Function GetItemsByTypeAndAccountNumber(typeID As Integer, _strAccountNumber As String) As List(Of Item)
Try
' We need to get all the results, one page at a time.
Dim iResultsPerPage As Integer = MaxPaging
Dim bCompleteFlag As Boolean = True
Dim iPageCounter As Integer = 1
Dim tempList As New List(Of Item)()
            Dim retList As New List(Of Item)()

            if (typeID == 1)
            // Get all records narrow down by account number
retList = WCFServiceReference.GetAllRecords(accountNumber, iPageCounter, iResultsPerPage, out bCompleteFlag).ToList(Of Item)();
            else
            retList = WCFServiceReference.GetAllRecords(iPageCounter, iResultsPerPage, out bCompleteFlag).ToList(Of Item)();

If retList IsNot Nothing Then
' We got results, but we need to check and see if there are more results
While Not bCompleteFlag
' try getting the next page
iPageCounter += 1
           if (typeID == 1)
            // Get all records narrow down by account number
retList = WCFServiceReference.GetAllRecords(accountNumber, iPageCounter, iResultsPerPage, out bCompleteFlag).ToList(Of Item)();
            else
            retList = WCFServiceReference.GetAllRecords(iPageCounter, iResultsPerPage, out bCompleteFlag).ToList(Of Item)();
' add it to the main list
For Each i As Item In tempList
retList.Add(i)
Next

' clear the temp list
tempList.Clear()
End While
End If
Return retList
Catch ex As Exception
Throw New Exception("Error getting records from the service layer: " + ex.Message, ex)
End Try
End Function

Service Producing WCF Layer Paging

C# Code Version

public List<Item> GetAllRecords(string accountNumber, int iPageNumber, int iResultsPerPage, out bool bCompleteFlag)
{
        int iTotalResults = 0;                  
        int iTotalPages = 0;                    
        bCompleteFlag = true;                      
        int iStartIndex = 0;                      
        List<Item> returnList = new List<Item>();  
        List<Item> recordList = new List<Item>();

  recordList = WCFServiceReference.ERPInterfaceGetTransactions(accountNumber).ToList<Item>();
        iTotalResults = recordList.Count();
        iTotalPages = (int)System.Math.Ceiling((decimal)(iTotalResults / iResultsPerPage));
        // check the bounds on the requested page number
        if (iPageNumber > iTotalPages)
        {
             iPageNumber = iTotalPages;
        }
        else if (iPageNumber < 1)
        {
             iPageNumber = 1;
        }
        iStartIndex = (iPageNumber - 1) * iResultsPerPage; 
        var i = recordList.Skip(iStartIndex).Take(iResultsPerPage);
        iTotalResults = recordList.Count;
        if (iPageNumber > 0)     // If it's <= 0, we'll just give all the results
        {
             iPageNumber -= 1;    // Start by adjusting the page index for zero-based indices
             iStartIndex = iPageNumber * iResultsPerPage;    // For example, page num = 2, results/page = 10, 
             int iEndIndex = iStartIndex + iResultsPerPage;  // We need to stop at the right place 
             if (iEndIndex >= recordList.Count)
             {
                  bCompleteFlag = true;
                  iEndIndex = recordList.Count;
             }
             else
             {
                  bCompleteFlag = false;
             }
             for (int i = iStartIndex; i < iEndIndex; i++)
             {
                  returnList.Add(recordList[i]);
             }
         // Return a small subset                
             recordList = returnList;
        }
        return recordList;
}

VB.NET Code Version

Public Function GetAllRecords(accountNumber As String, iPageNumber As Integer, iResultsPerPage As Integer, ByRef bCompleteFlag As Boolean) As List(Of Item)
     Dim iTotalResults As Integer = 0
     Dim iTotalPages As Integer = 0
     bCompleteFlag = True
     Dim iStartIndex As Integer = 0
     Dim returnList As New List(Of Item)()
     Dim recordList As New List(Of Item)()

     recordList = WCFServiceReference.ERPInterfaceGetTransactions(accountNumber).ToList(Of Item)()
     iTotalResults = recordList.Count()
     iTotalPages = CInt(Math.Truncate(System.Math.Ceiling(CDec(iTotalResults \ iResultsPerPage))))
     ' check the bounds on the requested page number
     If iPageNumber > iTotalPages Then
          iPageNumber = iTotalPages
     ElseIf iPageNumber < 1 Then
          iPageNumber = 1
     End If
     iStartIndex = (iPageNumber - 1) * iResultsPerPage
     Dim i = recordList.Skip(iStartIndex).Take(iResultsPerPage)
     iTotalResults = recordList.Count
     If iPageNumber > 0 Then
          ' If it's <= 0, we'll just give all the results
          iPageNumber -= 1
          ' Start by adjusting the page index for zero-based indices
          iStartIndex = iPageNumber * iResultsPerPage
          ' For example, page num = 2, results/page = 10, 
          Dim iEndIndex As Integer = iStartIndex + iResultsPerPage
          ' We need to stop at the right place 
          If iEndIndex >= recordList.Count Then
               bCompleteFlag = True
               iEndIndex = recordList.Count
          Else
               bCompleteFlag = False
          End If
          For i As Integer = iStartIndex To iEndIndex - 1
               returnList.Add(recordList(i))
          Next
          ' Return a small subset                
          recordList = returnList
     End If
     Return recordList

From hop 4 (Node 5) – ERP with Application Servers Configuration Optimization:

This section lists web sites that explain how to optimize the front-end application servers of back-end ERP systems, such as SAP, Oracle ERP, or Lawson ERP. As back-end ERP systems were adapted to operate on the Internet, application servers became a viable solution for hosting legacy applications, and exposing ERP modules.

For additional information on Apache Server performance tuning, see http://httpd.apache.org/docs/2.0/misc/perf-tuning.html.

For additional information on WebLogic Server performance tuning, see http://download.oracle.com/docs/cd/E13222_01/wls/docs100/perform/WLSTuning.html#wp1152088.

For additional information on IBM WebSphere performance tuning, see http://www-01.ibm.com/software/webservers/appserv/was/performance.html.

The majority of application servers use Java. For more information on how to fine tune Java, go to http://java.sun.com/performance/reference/whitepapers/tuning.html.

Conclusion

SOA, or enterprise integration, integrates standard and non-standard technologies in an end-to-end solution that addresses a variety of business objectives. Implementing such a complex architecture requires detailed analysis, and highly disciplined design, development, and deployment initiatives. This article discussed the many tools that are available from Microsoft for configuring, fine-tuning, troubleshooting, and monitoring the performance of WCF services. There are also guidelines on how to design your solutions for performance and scalability. Finally, it included a broad range of configuration options for the end-to-end solution, from the client to the back-end ERP. It is recommended that you read the other articles that were mentioned here to get a better understanding of how to configure and troubleshoot your integration scenarios.

Additional Resources

https://support.microsoft.com/kb/821268.

For additional information about optimizing IIS 6.0, see "Optimizing IIS 6.0 Performance" on TechNet at https://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/e621190d-1015-40c2-a5ec-0dcb32c98286.mspx?mfr=true.

For additional information about optimizing IIS 7.0, see "Optimizing IIS 7.0 Performance" on TechNet at https://technet.microsoft.com/en-us/library/cc770381(WS.10).aspx

"Configuring Windows Communication Foundation Applications" on MSDN at https://msdn.microsoft.com/en-us/library/ms730120.aspx

"Windows Communication Foundation Configuration Schema" on MSDN at https://msdn.microsoft.com/en-us/library/ms731734.aspx

There is a useful discussion with procedures on optimizing the data access layer at this link: http://www.linkedin.com/answers/technology/software-development/TCH_SFT/416855-13606449

For additional information on Apache Server performance tuning, see http://httpd.apache.org/docs/2.0/misc/perf-tuning.html.

For additional information on WebLogic Server performance tuning, see http://download.oracle.com/docs/cd/E13222_01/wls/docs100/perform/WLSTuning.html#wp1152088.

For additional information on IBM WebSphere performance tuning, see http://www-01.ibm.com/software/webservers/appserv/was/performance.html.

The majority of application servers use Java. For more information on how to fine tune Java, go to http://java.sun.com/performance/reference/whitepapers/tuning.html.

Previous article: Performance and Scalability

Continue on to the next article: Dependency Injection in Windows Communication Foundation