IIS Site Warm Up

Published:
Hey folks, 'bout time for me to come around with a little tip.

Thanks to IIS 7.5 Extensions and Microsoft (well... really Windows 8, and IIS 8 I guess...), we can now prime our Application Pools, when IIS starts.

Now, though it would be nice to be able to simply plug it in and go, unfortunately this is not the case, and there is some configuring to do.

Please see here: http://learn.iis.net/page.aspx/1089/iis-80-application-initialization/

Now, this article is not about the IIS extension, this is about priming or warming up your site.

Now, this is not a necessity, but if you are like me, you take advantage of .Net's Runtime.Caching, so simply priming your App Pools may not be enough.  My SRE (Site Rendering Engine) for one highly utilizes the server's in memory cache, as well as the Runtime.Cache, so the very first load takes a bit.

When we can prime the site itself, we can ensure that hits to it after the fact will be quick.  Thus the need for a WarmUp.

What I've done is pretty simple, yet extremely effective in doing just this.   All it does is fire up a WebClient, passes a valid User-Agent header, and pulls the site.

NOTE:  This is not limited to IIS 7.5.  It should work on any windows system, so long as it has the .Net 4 framework installed.

Here is some code for you all.  Mind you it is a VS 2010 project, so I will attach the source files as well.  Make sure to modify the Settings.xml file, just replace the url and page attributes with whatever you need to prime, you can add as many sites as you need.

It is a console application, so there are no buttons to push, there are 2 classes, and a settings file.

AuditManager.vb
Public Class AuditManager
                      
                          Public Enum AuditType
                              Exception
                              General
                          End Enum
                      
                          Public Shared Function GetPath() As String
                              Return System.AppDomain.CurrentDomain.BaseDirectory()
                          End Function
                      
                          Public Shared Sub Write(ByVal _Type As AuditType?, ByVal _Description As String, Optional ByVal _Location As String = Nothing, Optional ByVal _Except As Exception = Nothing)
                              Dim _Stack As System.Diagnostics.StackTrace
                              If _Except IsNot Nothing Then
                                  _Stack = New System.Diagnostics.StackTrace(_Except, True)
                              Else
                                  _Stack = Nothing
                              End If
                              Using _F As New IO.StreamWriter(GetPath() & FormatDateTime(Date.Now, DateFormat.ShortDate).Replace("/", String.Empty) & ".LOG", True)
                                  Dim tmpString As New Text.StringBuilder
                                  tmpString.Append("-------------------------------------------------" & vbCrLf)
                                  tmpString.Append("WHEN:" & vbCrLf)
                                  tmpString.Append(Date.Now & vbCrLf)
                                  If _Type.HasValue Then
                                      tmpString.Append("-------------------------------------------------" & vbCrLf)
                                      tmpString.Append("TYPE:" & vbCrLf)
                                      tmpString.Append([Enum].GetName(GetType(AuditType), _Type) & vbCrLf)
                                  End If
                                  If _Location IsNot Nothing Then
                                      tmpString.Append("-------------------------------------------------" & vbCrLf)
                                      tmpString.Append("LOCATION:" & vbCrLf)
                                      tmpString.Append(_Location & vbCrLf)
                                  End If
                                  tmpString.Append("-------------------------------------------------" & vbCrLf)
                                  If _Stack IsNot Nothing Then
                                      tmpString.Append("STACKTRACE:" & vbCrLf)
                                      tmpString.Append(_Stack.ToString() & vbCrLf)
                                      tmpString.Append("-------------------------------------------------" & vbCrLf)
                                      tmpString.Append("STACK FRAMES:" & vbCrLf)
                                      For Each frame In _Stack.GetFrames()
                                          tmpString.Append(" - FILE:" & frame.GetFileName() & vbCrLf)
                                          tmpString.Append(" - METHOD:" & frame.GetMethod().Name & vbCrLf)
                                          tmpString.Append(" - LINE:" & frame.GetFileLineNumber() & vbCrLf)
                                          tmpString.Append(" - COLUMN:" & frame.GetFileColumnNumber() & vbCrLf)
                                      Next
                                  End If
                                  If _Except IsNot Nothing Then
                                      tmpString.Append("-------------------------------------------------" & vbCrLf)
                                      tmpString.Append("SOURCE:" & vbCrLf)
                                      tmpString.Append(_Except.Source & vbCrLf)
                                      tmpString.Append("-------------------------------------------------" & vbCrLf)
                                      tmpString.Append("MESSAGE:" & vbCrLf)
                                      tmpString.Append(_Except.Message & vbCrLf)
                                      tmpString.Append("-------------------------------------------------" & vbCrLf)
                                      tmpString.Append("DATA:" & vbCrLf)
                                      tmpString.Append(_Except.Data.ToString() & vbCrLf)
                                  End If
                                  tmpString.Append("-------------------------------------------------" & vbCrLf)
                                  tmpString.Append("NOTES:" & vbCrLf)
                                  tmpString.Append(_Description & vbCrLf)
                                  tmpString.Append("-------------------------------------------------" & vbCrLf)
                                  _F.Write(tmpString.ToString())
                                  _F.Close()
                              End Using
                          End Sub
                      
                      End Class

Open in new window


WarmUpService.vb
Imports System.Reflection
                      Imports System.IO
                      Imports System.Net
                      Imports System.Threading.Tasks
                      
                      Module WarmUpService
                      
                          Private _SiteList As New List(Of Typing)
                      
                          Public Sub Main()
                              AuditManager.Write(AuditManager.AuditType.General, "Fireing Up...")
                              DoTheWarmUp()
                              AuditManager.Write(AuditManager.AuditType.General, "All Set...")
                          End Sub
                      
                          Private Sub DoTheWarmUp()
                              Try
                                  Parallel.Invoke(Sub()
                                                      SetAllowUnsafeHeaderParsing20()
                                                  End Sub,
                                                  Sub()
                                                      Dim _X As XElement = XElement.Load(AuditManager.GetPath() & "Settings.xml")
                                                      _SiteList = (From n In _X...<Site>.AsParallel()
                                                                  Select New Typing() With {
                                                                      .Page = n.@page,
                                                                      .Url = n.@url
                                                                  }).ToList()
                                                      Parallel.ForEach(_SiteList, Sub(Item)
                                                                                      Using _WC As New WebClient()
                                                                                          _WC.Headers.Add("user-agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13")
                                                                                          _WC.DownloadData(Item.Url & Item.Page)
                                                                                      End Using
                                                                                  End Sub)
                                                  End Sub)
                              Catch ex As Exception
                                  AuditManager.Write(AuditManager.AuditType.Exception, "There was an issue!", "DoTheWarmUp", ex)
                              End Try
                          End Sub
                      
                          Private Sub SetAllowUnsafeHeaderParsing20()
                              Dim a As New System.Net.Configuration.SettingsSection
                              Dim aNetAssembly As System.Reflection.Assembly = Assembly.GetAssembly(a.GetType)
                              Dim aSettingsType As Type = aNetAssembly.GetType("System.Net.Configuration.SettingsSectionInternal")
                              Dim args As Object() = Nothing
                              Dim anInstance As Object = aSettingsType.InvokeMember("Section", BindingFlags.Static Or BindingFlags.GetProperty Or BindingFlags.NonPublic, Nothing, Nothing, args)
                              Dim aUseUnsafeHeaderParsing As FieldInfo = aSettingsType.GetField("useUnsafeHeaderParsing", BindingFlags.NonPublic Or BindingFlags.Instance)
                              aUseUnsafeHeaderParsing.SetValue(anInstance, True)
                          End Sub
                      
                          Partial Public Class Typing
                              Public Property Url As String
                              Public Property Page As String
                          End Class
                      
                      End Module

Open in new window


And Settings.xml
<Settings>
                        <Site url="http://www.o7thwebdesign.com" page="/" />
                        <Site url="http://www.facchinifacchinipa.com" page="/" />
                        <Site url="http://skor.in" page="/" />
                        <Site url="http://o7t.in" page="/" />
                      </Settings>

Open in new window


Compile it up, let it run, and warmup your sites properly.  Personally, I added a installer project, and simply added it to the server's startup so it runs everytime MS decided it needs to restart my machine for updates...
0
4,579 Views

Comments (0)

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.