Web Services (ASMX 1.1) Performance Guidelines - Timeouts

From Guidance Share

Jump to: navigation, search

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



Contents

Set Your Proxy Timeout Appropriately

When you call a Web service synchronously, set the Timeout property of the Web service proxy. The default value is 100 seconds. You can programmatically set the value before making the call, as shown in the following code snippet.


  MyWebServ obj = new MyWebServ();
 obj.Timeout = 15000; // in milliseconds

For ASP.NET applications, the Timeout property value should always be less than the executionTimeout attribute of the httpRuntime element in Machine.config. The default value of executionTimeout is 90 seconds. This property determines the time ASP.NET continues to process the request before it returns a timed out error. The value of executionTimeout should be the proxy Timeout, plus processing time for the page, plus buffer time for queues.

  • Consider reducing the Proxy Timeout value from its default of 100 seconds if you do not expect clients to wait for such a long time. You should do this even under high load conditions when the outbound requests to the Web service could be queued on the Web server. As a second step, reduce the executionTimeout also.
  • You might need to increase the value if you expect the synchronous call to take more time than the default value before completing the operation. If you send or receive large files, you may need to increase the attribute value. As a second step, increase the executionTimeout attribute to an appropriate value.


Set Your ASP.NET Timeout Greater Than Your Web Service Timeout

The Web service timeout needs to be handled differently, depending upon whether you call the Web service synchronously or asynchronously. In either case, you should ensure that the timeouts are set to a value less than the executionTimeout attribute of the httpRuntime element in Machine.config. The following approaches describe the options for setting the timeouts appropriately:

  • Synchronous calls to a Web service. Set the proxy Timeout to an appropriate value, as shown in the following code snippet.
  MyWebServ obj = new MyWebServ();
  obj.Timeout = 15000; // in milliseconds

You can also set the value in the proxy class generated by the WSDL for the Web service. You can set it in the class constructor, as shown in the following code snippet.


  public MyWebServ() {
      this.Url = "http://someMachine/mywebserv/myserv.asmx";
      this.Timeout = 10000;  //10 seconds
  }

Or you can set it at the method level for a long-running call.


  public string LengthyProc(int sleepTime) {
    this.Timeout = 10000; //10 seconds
    object[] results = this.Invoke("LengthyProc", new object[] {sleepTime});
    return ((string)(results[0]));  
  }
  • Asynchronous calls to a Web service. In this case, you should decide on the number of seconds you can wait for the Web service call to return the results. When using a WaitHandle, you can pass the number of milliseconds the executing thread is blocked on the WaitHandle before it aborts the request to the Web service. This is shown in the following code snippet.


  MyWebServ obj = new MyWebServ();
  IAsyncResult ar = obj.BeginFunCall(5,5,null,null);
  // wait for not more than 2 seconds
  ar.AsyncWaitHandle.WaitOne(2000,false);
  if (!ar.IsCompleted) //if the request is not completed  { 
    WebClientAsyncResult wcar = (WebClientAsyncResult)ar;
    wcar.Abort();//abort the call to web service 
  }
  else
  { //continue processing the results from web service }


Abort Connections for ASP.NET Pages That Timeout Before a Web Services Call Completes

After you make the configuration changes described in the previous section, if your Web pages time out while Web services calls are in progress, you need to ensure that you abort the Web services calls. This ensures that the underlying connections for the Web services calls are destroyed.

To abort a Web services call, you need a reference to the WebRequest object used to make the Web services call. You can obtain this by overriding the GetWebRequest method in your proxy class and assigning it to a private member of the class before returning the WebRequest. This approach is shown in the following code snippet.


  private WebRequest _request;
  protected override WebRequest GetWebRequest(Uri uri){
    _request = base.GetWebRequest(uri);
    return _request;
  }

Then, in the method that invokes the Web service, you should implement a finally block that aborts the request if a ThreadAbortException is thrown.


  [System.Web.Services.Protocols.SoapDocumentMethodAttribute(…)]
  public string GoToSleep(int sleepTime) {
    bool timeout = true;
    try {
      object[] results = this.Invoke("GoToSleep", new object[] {sleepTime});
      timeout = false;
      return ((string)(results[0]));  
    } 
    finally {
      if(timeout && _request!=null)
        _request.Abort();
    }
  }

Note Modifying generated proxy code is not recommended because the changes are lost as soon as the proxy is regenerated. Instead, derive from the proxy class and implement new functionality in the subclass whenever possible.


Consider the responseDeadlockInterval Attribute

When you make Web services calls from an ASP.NET application, if you are increasing the value of both the proxy timeout and the executionTimeout to greater than 180 seconds, consider changing the responseDeadlockInterval attribute for the processModel element in the Machine.config file. The default value of this attribute is 180 seconds. If there is no response for an executing request for 180 seconds, the ASP.NET worker process will recycle.

You must reconsider your design if it warrants changing the attributes to a higher value.

Personal tools