Consolidation of Application Pools

Automated Consolidation of Application Pools

SharePoint leverages IIS, and runs within Application Pools.  One should recognize up front that there are two distinct categories of Application Pools used in SharePoint; Web Application pools and Service Application Pools.


Application Pools consume an estimated 80-100MB RAM each, and possibly a lot more, depending on usage.  These appear as w3wp.exe processes in Task Manager.  When you have a number of w3wp processes running, it can be hard to tell them apart; which is for a given web or service application?  Here’s a way to get the PID (Process ID) for each worker process, along with the user-friendly name, so you can correlate each w3wp process:

cd C:WindowsSystem32inetsrv appcmd.exe list wp
[/sourcecode ]
A nice listing of Web Application Pools is generated by this single command.  It ensures the fields are not truncated, and is extensible to allow display of any properties/columns you wish:
get-SPWebApplication | select displayname, url, applicationpool | format-table -autosize | out-string -width 2000
[/sourcecode ]
Note the CmdLet "get-SPWebApplication".  For Service Application Pools, the CmdLet is "Get-SPServiceApplicationPool", as in:
Get-SPServiceApplicationPool | select Id, Name, DisplayName, processaccountname
[/sourcecode ]
Within IIS, the Service Application Pools are identified by GUID.  Their mapping can be explored individually by examining the application pool binding, but this is a bit laborious.
<h1>Removing a Service Application Pool</h1>
To remove a Service Application Pool by name, you can use:
Remove-SPServiceApplicationPool -Identity "Your Orphaned SharePoint Service Application Pool Name"</pre>
[/sourcecode ]
My own preference is to first consolidate the application pools, then in IIS quiesce the desired application pools, and only once things are truly running smoothly, they can be removed.  It is important to do the removing and adding in PowerShell and not directly in IIS.  This will ensure that the correct IIS configuration gets propagated to all current and future WFEs (Web Front Ends).
<h1>Consolidating Web Application Pools programmatically</h1>
Consolidating Web Application Polls is quite easy.  If you do not have security driven segregation of Application Pools, you can consider doing so.  Note I have received conflicting advice on doing this.   Todd Klindt who I hold in the highest regard recommends considering consolidation.  Microsoft does advise quite a low maximum number of Application Pools, yet their support staff have advised segregation.
First let's grab an existing Application Pool, and simply reassign it to the target Web Application Pool:
$sourceWebAppPool = (Get-SPWebApplication &lt; URL of a webapp whose application pool you want to use&gt;).ApplicationPool 
$webApp = Get-SPWebApplication &lt; URL of the web application you want to change&gt; 
$webApp.ApplicationPool = $sourceWebAppPool 

Lather, rinse, and repeat for each of your Web Apps to be consolidated…

Note that there is no SharePoint CmdLet for creating an Application Pool.  You can use the IIS CmdLet, but I am not convinced this is a safe method, as right away I can see the service account is an IIS Service Identity reference, and the application pools have a different type and cannot be assigned to a web application directly.   here’s the CmdLet for reference:

Import-Module WebAdministration
$appPool = New-WebAppPool “My new App Pool”
[/sourcecode ]
If you need to segregate previously consolidated web application application pools, the following round-about procedure is safe and works:

  1. Create a brand new temporary Web Application and associated pool
  2. Reassign your target web app’s pool, as described above
  3. Destroy the temporary Web Application

The sequence is key.  If you destroy the temporary web application, the associated pool is destroyed with it, because there are no other associated applications.  In contrast, once you assign a second web application to this new application pool, the application pool will not be destroyed when the temporary web application is removed.

Consolidating Service Application Pools programmatically

On some farms I’ve inherited, there is a profusion of unnecessary Service Application Pools.  Note there are reasons to isolate distinct service application pools, generally around security and multi-tenancy.

I wanted to consolidate my Service application pools but in a safe and programmatic manner.  While you can change the account associated with a service application, there is the risk that the new service account won’t quite have the necessary access.  When SharePoint does automatically grant access to the new service account, it won’t remove access from the original service account.  Lastly, one needs to make sure the new service account is configured as a managed account.  Lastly, SharePoint doesn’t support managed service accounts for all service applications.  Exceptions do include the User Profile Service ADSync account, unattended user accounts (Excel, Visio, PerformancePoint), search crawl accounts (Foundation, Enterprise, and FAST), and the two Object Cache Portal Accounts (which are configured for each Web Application for performance reasons).

Not every Service Application runs under an Application Pool; some run under the Farm’s pool, and hence can’t be directly reassigned. Farm-wide service applications have one and only one instance in the farm.  So the Security Token Service Application, Web Usage Application (WS_UsageApplication), State Service and Application Registry Service Application don’t run under their own Application Pools, and their CmdLets are simpler.  So while one can create multiple Session State Service Applications and corresponding databases, there’s only one State Service Application.  The script below lists them by name in an array and makes sure not to even try to remap these.  For good measure I include the FAST Content Service Application in this category.  Note yours may be named differently.

Next, I wanted to start with a clean Service Application Pool named clearly denoting the desired service account.

$MyRefAppPool=new-spserviceapplicationpool -name “SPService Service Application Pool” -account “YourDomainspservice”
$SPaps = get-spserviceapplication 
for ($i=0;$i -lt $SPaps.Count; $i++)
$SPap = $SPaps[$i];     
#Some service applications run at the farm level and don’t have selectable application pools, hence is it wiser to filter these out up front. 
if (@(“SecurityTokenServiceApplication”,”Application Registry Service “,”FASTContent”,”State Service”,”WSS_UsageApplication”,””) -notcontains $SPAP.DisplayName)  
#Don’t mix & match the application pools and accounts, best is to consolidate along the lines of existing process accounts, to avoid permissions issues  
if ($testAppPool.ProcessAccountname -eq $MyRefAppPool.processaccountname)   
write-host “Processing  $($ because it has the target process account: $($MyRefAppPool.processaccountname)”
            $SPAp.update()  #update() is actually required.  You will notice a processing delay during the update
write-host “Skipping $($ because it has a different process account: $($SPAp.get_applicationpool().ProcessAccountname)”
   write-host “Skipping $($ because it had an error”
[/sourcecode ]
An IISReset at this point is advisable.  Lastly, you can go into IIS after running this, view Application pools, and “Stop” the GUID named Application Pools with zero associated Applications.  Another IISReset is advisable to ensure you are recovering your RAM.

For a more general overview of Application Pool configuration, please see TechNet.

Compression in IIS

There’s a relatively obscure setting in IIS that can have a dramatic effect on the performance perceived by SharePoint users.  By enabling IIS to compress the communication to the user, communication to the user can consume less bandwidth.  The trade-off is with CPU usage to compress the messages.  Note the setting is quite fine-grained, allowing you to find the optimal balance of bandwidth conversation against the available SharePoint farm WFE (Web Front End) CPU.

If you open a simple CMD window on your SharePoint WFE, run the following commands (all commands below assume this drive and directory):

c: CD WindowsSystem32Inetsrv appcmd list config -section:httpcompression

This will show you the current compression settings.   Note there are two categories of compression: Static and Dynamic.  We will want to set both.  There are more than one compression mechanism.  GZip is recommended.  The compression can be set between 0 (no compression) and 9 (ultimate).  I would suggest the sweet spot is between 4 and 7 (your mileage may vary).  Here’s the command:

Appcmd.exe  set config -section:httpCompression   -[name='gzip'].staticCompressionLevel:9   -[name='gzip'].dynamicCompressionLevel:7

I look at each environment; not just Production, but Dev and UAT environments.  Where are they located?  How many CPUs are available?  If you are running below Microsoft CPU minimums (shame on you!) then perhaps adding to the CPU load isn’t for you.  If you access your environment over a thin pipe to a remote location, then IIS Compression can make a significant difference in performance.

Let’s look a bit closer at Dynamic Compression.  There are two settings that control when compression is enabled and disabled.  The default is that when the CPU utilization is below 50% compression gets enabled.  Above 90% compression gets disabled.  The CPU utilization is sampled by IIS every 30 seconds.  I think 90% CPU utilization is rather high, given all the SharePoint wonderfulness going on in my farm, so I crank these settings down a bit with these two commands:

appCmd set config -section:httpCompression /dynamicCompressionDisableCpuUsage:50 appCmd set config -section:httpCompression /dynamicCompressionEnableCpuUsage:30

There is a setting to control the minimum size of the object before compression is applied.  The default is 256 bytes.  This applies the overhead of compression to some pretty small files.  You can choose to increase it to 512:

appCmd set config -section:httpCompression /MinFileSizeForComp:512

I found a dramatic improvement in perceived SharePoint performance for users connected over a thin pipe to SharePoint.  This includes remote users.  Give it a try, and let me know what you experience!  For more information, please reference Bill Baer’s in-depth TechNet article.

Redirect to Friendly URLs in SharePoint

It’s hard to pull the plug on an old URL host name in favor of a new one. Sure AAM (Alternate Access Methods) allows for the definition of up to five hostnames (one per zone) on the same Web Application, but there are wrinkles to having alternate hostnames floating about.

For just one example, Contextual Search (searching on a list or site) will only work if you your search crawl is on the default zone, and if the user is using the default zone. Otherwise there will be no search results returned.  Sometimes the goal is to retire a hostname, and perhaps we want to have a transition period where users are redirected to the new URL.

You can have URLs redirected to your preferred host very simply using an add-on to IIS from Microsoft called “IIS Redirect 2.0” available from this site, just be sure to install the x64 version.

The preferred form of redirect in this case is a 301.  It is respected by search engines, and allows browsers the possibility to correct bookmarks.   As per RFC2616, search engines should forget the redirecting address and save the address pointed to by the redirection as the preferred address.

Once you’ve installed “IIS Redirect 2.0”, go into IIS (no reboot required), and find the target site:

Enter URL Redirect through a double-click or right-click properties, and add a rule:

I suggest a Canonical domain name rule:

Simply choose the preferred URL to retain; all other ways in get the redirect to this URL:

You can view the Rule that’s created. It’s simply a regular expression match on anything that’s different from your preferred URL and a redirect to your preferred URL:

An IISReset is always advisable.  Happy Redirecting!