The application has been developed and tested, the pre-deployment checklist has been satisfied, and deployment is completed. Now it’s time to keep an eye on things and consider what changes might be necessary in the real world. You will need to monitor performance counters and consider other configuration changes to satisfy production demands.
The key point to monitoring the performance of a deployed ASP.NET application is to understand that performance is really a complex balancing act. Incoming requests can be handled very quickly if the content is cached. However, caching content increases the memory consumption and can put additional pressure on the system to page memory to disk. This becomes even more complex when you add that the application is running in a garbage-collected environment that is periodically preempting other work in order to clean up unused memory.
You can gather some data from Windows performance counters on the server in order to monitor how it is running, using the Perfmon tool that comes with Windows. Don’t focus entirely on a single performance metric. You can find an excellent article, “ASP.NET Performance Monitoring, and When to Alert Administrators,” by Thomas Marquardt of the ASP.NET team on the MSDN site at http:// msdn2.microsoft.com/en-us/library/ms972959.aspx. Marquardt recommends a specific set of performance counters as the minimum set to watch. Among other counters, his list includes:
Processor(_Total)\% Processor Time and Process(aspnet_wp)\% Processor Time -If the total processor time is consistently high and the ASP.NET worker process isn’t responsible, the web application may be getting starved for processing power because of other things happening on the machine. If the worker process time is consistently high, it may indicate that you are hitting the limit of the load the machine can handle.
Process(aspnet_wp)\Private Bytes - The private bytes counter indicates how much memory the process has committed. A steady increase is a good indicator that something in the application is allocating resources that aren’t being returned to the system. This will lead to problems of process recycling and should be investigated.
Process(aspnet_wp)\Virtual Bytes - The virtual bytes correspond to the virtual address space the process has consumed. As this approaches the limit of 2GB (or optionally 3GB in 64-bit environments where it is enabled), it indicates that the address space is becoming fragmented. Items held in a cache may still be pinned, while other transient use of memory has been returned. Just as defragmenting your hard drive can improve performance, so can defragment-ing the address space of the worker process. However, there isn’t a great way to do this now, so the solution is to recycle the worker process. ASP.NET will do this for you automatically. The threshold at which this happens is configured as the Maximum Virtual Memory setting, found in the Internet Services Manager on the Recycling tab for the Application Pool.
ASP.NET\Application Restarts - Application restarts incur a cost of compilation checks and starting from scratch in populating the cache. Keep an eye out for excessive application restarts that can be caused by tools touching key files like machine.config or web.config. This problem is known to be a side effect of some virus scanning tools.
ASP.NET\Requests Rejected - Rejected requests are bad. The server refused to deliver a page to someone trying to access the web application. When requests queued and requests executing exceed a limit, ASP.NET will start rejecting requests in order to catch up.
Monitoring this small set of performance counters can give you insight into how healthy the application is after it has been deployed and can alert you to problems. Several commercial tools are available that will monitor performance counters and can be configured to send mail, page you, or even call you when thresholds are exceeded.
The system.web.extensions section itself is essentially all commented out except for the structure definition. By default, the JSON serializer of ASP.NET limits the length of JSON strings that it will consume. If the incoming data exceeds the limit, an exception is thrown. This is to guard against wasting processing power on excessively long strings. The jsonSerialization section lets you customize the limit on JSON strings that will be processed. It can also accept a definition of custom converters for seri-alizing and deserializing additional types.
<system.web.extensions> <scripting> <webServices> <!-- Uncomment this line to customize maxJsonLength and add a custom converter --> <!- <jsonSerialization maxJsonLength="500"> <converters> <add name="ConvertMe" type="Acme.SubAcme.ConvertMeTypeConverter"/> </converters> </jsonSerialization> -->
Script access to the ASP.NET application services is not enabled by default; you must turn them on explicitly. The authentication service can be configured to reject requests that aren’t using SSL for security. The profile service must be enabled if you want to use it. You also have to define what properties are available for reading or writing remotely from script.
<!- <authenticationService enabled="true" requireSSL = "true|false"/> --> <!- <profileService enabled="true" readAccessProperties="propertyname1,propertyname2" writeAccessProperties="propertyname1,propertyname2" /> --> </webServices>
In the scriptResourceHandler section, you control whether or not requests for dynamic script are compressed or cached; normally, you want these features:
<!- <scriptResourceHandler enableCompression="true" enableCaching="true" /> --> </scripting> </system.web.extensions>
IIS7 also introduces a new configuration section for your web.config file: system.webServer. IIS7 supports two modes: classic and integrated. Classic mode preserves backward compatibility in the way that ISAPI filters and extensions are called. In integrated mode, the old model is replaced by a new pipeline where the two separate lifecycles of IIS and ASP.NET are merged into one for greater efficiency. The ScriptModule is added to the integrated mode pipeline. The httpHandler modifications made in the system.web section are duplicated in the handlers section of the new section.
This change isn’t specific to ASP.NET AJAX but you should be aware of the validation element as it can cause confusion. The validateIntegratedModeConfiguration option is set to false. Setting this value to false means it is not an error to have duplicate entries in the handler and httpHandlers sections and the modules and httpModules sections.
<system.webServer> <validation validateIntegratedModeConfiguration="false"/> <modules> <add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </modules> <handlers> <remove name="WebServiceHandlerFactory-Integrated" /> <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> </handlers> </system.webServer>
The web.config template is a little large as a starting point but has everything necessary to get started and works across several versions of the web server. One common symptom of a configuration error with the ScriptResource handler is an error message in the browser stating that objects in the Sys namespace are not defined. This wouldn’t be typically associated with deployment, but given the separate definitions for different versions of IIS, it is something to be aware of when moving from test to production environments.