Web Services (ASMX 1.1) Performance Guidelines - Connections

From Guidance Share

Jump to: navigation, search

- J.D. Meier, Srinath Vasireddy, Ashish Babbar, and Alex Mackman


Contents

Configure The maxconnection Attribute

The maxconnection attribute in Machine.config limits the number of concurrent outbound calls.

Note This setting does not apply to local requests (requests that originate from ASP.NET applications on the same server as the Web service). The setting applies to outbound connections from the current computer, for example, to ASP.NET applications and Web services calling other remote Web services. The default setting for maxconnection is two per connection group. For desktop applications that call Web services, two connections may be sufficient. For ASP.NET applications that call Web services, two is generally not enough. Change the maxconnection attribute from the default of 2 to (12 times the number of CPUs) as a starting point.


 <connectionManagement>
   <add address="*" maxconnection="12"/>
 </connectionManagement> 

Note that 12 connections per CPU is an arbitrary number, but empirical evidence has shown that it is optimal for a variety of scenarios when you also limit ASP.NET to 12 concurrent requests (see the "Threading" section later in this chapter). However, you should validate the appropriate number of connections for your situation.

Increasing the maxconnection attribute results in increased thread pool and processor utilization. With the increase in the maxconnection value, a higher number of I/O threads will be available to make outbound concurrent calls to the Web service. As a result, you process incoming HTTP requests more quickly.

Before Making the Change

You should consider increasing the connections only if you have available CPU. You should always check processor utilization before increasing the attribute because increasing the attribute results in more work for the processor, as described above. For this reason, increasing this attribute makes sense only when your processor utilization is below the threshold limits (usually less than 75 percent utilization).


Evaluating the Change

Changing the attribute may involve multiple iterations for tuning and involves various trade-offs with respect to thread pool utilization. Therefore, the changes in the maxconnection attribute may require changes to other thread pool – related configuration attributes, such as maxWorkerThreads and maxIoThreads.

When you load test your application after making the configuration changes, you should monitor CPU utilization and watch the ASP.NET Applications\Requests/Sec and ASP.NET Applications\Requests in Application Queue performance counters. Requests in Application Queue should decrease while Requests/Sec and CPU utilization should increase.


Prioritize and Allocate Connections Across Discrete Web Services

Enumerate and prioritize the Web services you call. Allocate more connections to your critical Web services. You specify each Web service by using the address attribute as follows.


  <connectionManagement>
     <add address="WebServiceA" maxconnection="8">
     <add address="WebServiceB" maxconnection="4">
 </connectionManagement>

For example, if your application typically makes more requests to WebServiceA than WebServiceB, you can dedicate more connections, as shown in the example above.


Use a Single Identity for Outbound Calls

Use a single trusted identity for making Web services calls where you can. This helps limit the number of separate connection pools. Although you may need to create separate pools of connections for different discrete Web services, avoid creating pools per user. If you need to create pools per user, then specify a ConnectionGroupName when you call the Web service, but be aware that this hurts performance and leads to a large number of pools.

The connection pool your call uses is not determined by the identity of the caller. The ConnectionGroupName determines which connection pool is used. If separate identities use the same ConnectionGroupName, they use the same pool of connections, as shown in the following code snippet.


  // Create a secure group name.
  ….
  serv = new WebService1();
  // Set the PreAuthenticate property to send the authenticate request in 
  first go
  serv.PreAuthenticate=true;
  // Set the client side credentials
  ICredentials conCredentials = 
                new NetworkCredential("UserId","Password","NPSTest" );
  serv.Credentials = conCredentials;
  // Do not allow the server to auto redirect as this may compromise security
  serv.AllowAutoRedirect=false;
  // Use the same connectionGroup Name for all the calls
  serv.ConnectionGroupName = "SameForAllUsers";

You may need to create separate pools of connections for different discrete Web services or if you flow the identity of the original caller.

If ASP.NET calls Web services that allow anonymous callers, connections from the default connection pool are used. This is the default behavior unless you specify a ConnectionGroupName, as shown in above example.


Consider UnsafeAuthenticatedConnectionSharing with Windows Integrated Authentication

If your ASP.NET application calls a Web service that uses Microsoft Windows® integrated authentication, consider enabling UnsafeAuthenticatedConnectionSharing. By default, when you connect using Windows Integrated authentication, connections are opened and closed per request. This means that connections are not pooled by default. By enabling UnsafeAuthenticatedConnectionSharing, you keep connections open so they can be reused.

Consider the following guidelines:

  • If you are in a trusted environment and you connect using a single trusted identity, consider improving performance by setting UnsafeAuthenticatedConnectionSharing to true.
  //set the UnsafeAuthenticatedConnectionSharing to true
  myWebService.UnsafeAuthenticatedConnectionSharing = true;
  NetworkCredential myCred = new 
  NetworkCredential("UserA","PasswordA","DomainA");
  CredentialCache myCache = new CredentialCache();
  myCache.Add(new Uri("http://Someserver/WS/service1.asmx"), "NTLM", 
  myCred);
  myWebService.Credentials = myCache;
  myWebService.ConnectionGroupName = "SameName";
  string result = myWebService.HelloWorld();
  //as the ConnectionGroupName property is same for different client requests //only the first connection from above gets authenticated
  // the request below reuses the connection from above
  myCred = new NetworkCredential("UserB","PasswordB","DomainB");
  CredentialCache myCache = new CredentialCache();
  myCache.Add(new Uri("http://Someserver/WS/service1.asmx"), "NTLM", 
  myCred);
  myWebService.Credentials = myCache;
  myWebService.ConnectionGroupName = "SameName";
  result = myWebService.HelloWorld();
  • If you call a Web service by using the ASP.NET application original caller's identity, then you should avoid enabling UnsafeAuthenticatedConnectionSharing because connections would be shared across calls. Alternatively, you can enable UnsafeAuthenticatedConnectionSharing, and then assign users to individual connection groups by using a ConnectionGroupName. Either option is inefficient and results in a high number of pools.
  • If you need to connect to separate discrete Web services, assign calls to separate pools using ConnectionGroupName.
  • If you need to connect to a server that uses AuthPersistence (it authenticates a whole connection and not a single request), then you should set UnsafeAuthenticatedConnectionSharing to true, and specify some random connection group name. You will need to determine which application requests will go to that connection group because the server will no longer challenge for authentication on that connection.


References

  • For more information about AuthPersistence, see Microsoft Knowledge Base article 318863, "HOW TO: Modify the AuthPersistence Metabase Entry Controls When Clients Are Authenticated," at http://support.microsoft.com/default.aspx?scid=kb;en-us;318863.
  • For more information on UnsafeAuthenticatedConnectionSharing, see the .NET Framework documentation.


Use PreAuthenticate with Basic Authentication

If you use Basic authentication, the proxy's PreAuthenticate property can be set to true or false. Set it to true to supply specific authentication credentials to cause a WWWauthenticate HTTP header to be passed with the Web request. This prevents the Web server from denying access to the request and performing authentication on the subsequent retry request.

Note Pre-authentication only applies after the Web service successfully authenticates the first time. Pre-authentication has no impact on the first Web request.


  private void ConfigureProxy( WebClientProtocol proxy, 
                            string domain, string username, 
                            string password )
  {
    // To improve performance, force pre-authentication
    proxy.PreAuthenticate = true;
    // Set the credentials
    CredentialCache cache = new CredentialCache();
    cache.Add( new Uri(proxy.Url),
            "Negotiate",     
            new NetworkCredential(username, password, domain) );
    proxy.Credentials = cache;
    proxy.ConnectionGroupName = username;
  }
Personal tools