Warm-up Script for Web Front End Servers (WFE) in Load Balanced SharePoint Farms


There are many PowerShell scripts available to warm up SharePoint environments but they do not all handle "warming-up" multiple WFE Servers.

Below is a combination of a few scripts I found:

One from Bram http://bramnuyts.be/tag/warmup-script/

and one from Todd http://www.toddklindt.com/blog/Lists/Posts/Post.aspx?ID=404 which makes use of the new V3 PowerShell changes but does not cater for a Load Balancer unless you edit the Hosts file on the server to point to itself.

 

The below script should be scheduled after your app pools have recycled and should be setup through a windows task schedule and must be run as a User that has at least Read access to all Site Collections.

Make sure the DisableLoopbackCheck is configured as per Method 1 http://support2.microsoft.com/kb/896861 on production environments or one of my posts http://blogs.technet.com/b/scottstewart/archive/2014/09/15/disableloopbackcheck-when-routing-through-a-load-balancer-powershell-sample-included.aspx

 

I suggest either creating an account and adding the User to each Web App User Policy or make sure your Site Collection Admin has access to each Site Collection.

STEPS

  1. OPEN POWERSHELL ISE OR POWERSHELL AS A FARM ADMIN
  2. COPY AND PASTE THE POWERSHELL BELOW (Between the "#--------------------------")
  3. TEST THE SCRIPT TO ENSURE NO ERRORS OCCUR
  4. SAVE THE FILE AS A .PS1 TYPE IN A DESIGNATED LOCATION e.g. c:\powershell\warmupscript.ps1
  5. SCHEDULE A WINDOWS TASK TO RUN AFTER THE LAST APPLICATION POOL IS RECYCLED (4am should be safe)

 

## PowerShell Starts here

#--------------------------------------------------

Add-PsSnapin Microsoft.SharePoint.PowerShell -erroraction silentlycontinue
  
 function get-webpage([string]$url,[System.Net.NetworkCredential]$cred=$null)
 {
   $bypassonlocal = $false
   $proxyuri = "http://" + $env:COMPUTERNAME
   $proxy = New-Object system.Net.WebProxy($proxyuri, $bypassonlocal)
   $wc = new-object net.webclient
   $wc.Proxy = $proxy
   if($cred -eq $null)
   {
     $cred = [System.Net.CredentialCache]::DefaultCredentials;
   }
    
   $wc.credentials = $cred;
   return $wc.DownloadString($url);
 }
 
 $cred = [System.Net.CredentialCache]::DefaultCredentials;

## This can be used if required to force using certain credentials
 #$cred = new-object System.Net.NetworkCredential("username","password","machinename")
 
#Get the Web Apps
 $apps = get-spwebapplication # -includecentraladministration (Central admin is not included as it is not running on my WFE Server)
 
 foreach ($app in $apps) {
   #Get the Site Collections
   $sites = get-spsite -webapplication $app.url -Limit All
  
   ### UNCOMMENT THE 2 LINES BELOW IF YOU ONLY WANT TO USE THIS AT SITE COLLECTION LEVEL - Not required if Sites are warmed up.
   #write-host $app.Url;
   #$html=get-webpage -url $app.Url -cred $cred;

  
   ###COMMENT OUT BETWEEN THE "=======" IF THERE ARE TOO MANY WEBs i.e. Sites and you don't want to warm them up.
   #==================
    foreach ($site in $sites) {
      foreach ($web in $site.AllWebs) {
      #get the webs i.e. Sites
          write-host $web.Url;
          $html=get-webpage -url $web.Url -cred $cred;
     }
    }
    #=================
 }

#--------------------------

 

Comments (11)

  1. Stephen says:

    Hi Scott
    Do you still recommend to disable loopback checks with a load-balanced SharePoint 2016/Windows server 2016 environment ?

    1. Hi Stephen, honestly I haven't looked at it recently but I don't really see any reason why it would no longer be needed unless there is something new I haven't seen yet.
      On a production environment though the most restrictive option should be used.

  2. Jens says:

    Hi Scott
    Correct me if I am wrong, but your script calls the public URLs. It doesn't matter if you run this script on every WFE, The requests are always going through the load balancer. The load balancer forwards the requests to any WFE and not to the one you called the script.
    Therefore it's possible, that some WFE servers are not warmed up.
    How do you make sure that every WFE is warmed up?
    Regards
    Jens

    1. Hi Jens, the URI is replaced with the current server so it forces a warmup on the specific server it is run on.
      Without that replacement then you would only be warming up one server all the time.
      Thanks,
      Scott

  3. Aleksander says:

    When you run the script in the background, seen the growth of the occupied space on your hard drive. Files in the folder "C:\Windows\SysWOW64\config\systemprofile\AppData\Local\Microsoft\Windows\Temporary Internet Files\" are not automatically deleted.

    Decision:

    Function IEWarm($Urladr){
    foreach ($url in $Urladr){
    $IE = New-Object -com internetexplorer.application;
    $IE.visible = $false;
    $IE.navigate($url);
    # Wait a few seconds and then launch the executable.

    while ($IE.Busy -eq $true) { Start-Sleep -Seconds 5; }
    }
    Get-Process iexplore | Stop-Process
    }

    $Url = "URL1","URL2","URL3"
    IEWarm($Url)

    $ folder = "C:\Windows\SysWOW64\config\systemprofile\AppData\Local\Microsoft\Windows\Temporary Internet Files\*"
    del $ folder -Recurse -Force # -WhatIf

    1. Hi Aleksander, it is possible as we are effectively caching the pages on the server so you should have a separate process to clean-up temp files on servers anyway.

  4. jim says:

    What about SharePoint Online? is there any way to make something like this work there? or is there another option to ensure that all sites have been warmed up Online?

  5. Greg Lambert says:

    Hi Scott-

    I have a few follow up questions. How do you know if this is working properly (hitting/warming up the local IIS Cache)? Also, do you have to add anything to the local Hosts file in your example?

    Thanks!

  6. Greg Lambert says:

    Hi Scott-
    Any thoughts on why I would get:
    Exception calling "DownloadString" with "1" argument(s): "The remote server returned an error: (400) Bad Request."

    The script errors for me on the following line:
    return $wc.DownloadString($url);

    I'm logged in with a user that has Full Control on all Web Applications in my farm.

    If I do a simple test like this I don't get any errors:
    $webclient = new-object System.Net.WebClient
    $webclient.UseDefaultCredentials = $true
    $webpage = $webclient.DownloadString("https://webapp.blah.com")

    What the heck am I missing 🙂

    Thanks!

  7. Hi Greg, you don't have to add anything to the hosts file on the servers. The script must be run on each WFE server that is setup on the load balancer. It's easiest to just create a windows task and schedule it for 5am daily. If you then want to test whether
    the warm-up is working then simply add an entry on your local PC's hosts file pointing to a WFE and see that the load time is fast indicating that it is cached. Change your local hosts file then to do the same check against each WFE server.

  8. Hi Greg, sorry, I missed this one. You need to grant the account running the Script, privileges. Best to just go to User policy for the web app and add full read or worst case full control. (NB: Use a Service account for this i.e. Farm Admin or web app
    account or something that won't violate any security rules)

Skip to main content