Coding, How to

Gracefully Drain Session from IIS Before Restarting/Stopping

 

I needed to do this recently when working with a team to automated releases of several websites.

The team have a fairly common setup. They’ve got more than one web server behind a load balancer, the load balancer calls a keep alive page to see if the servers are behaving and if they fail to respond stops sending them traffic until they’re healthy again.

What I wanted to do was rename the keep alive page, so the box stops getting new traffic, then wait for the existing sessions to complete and finally start updating it.

The second bit is key here, you don’t want customers using the site to get dropped mid-upload or form post.

I set about seeing what could be done with powershell and put together this little sample. It uses the IIS CmdLets to see how many sessions are still active and waits for them to complete before stopping IIS.

Thought it was a neat little sample worth sharing.

EDIT: I realized that the current script only looked at inflight http requests, I’ve put together a more complex script to interrogate the Active ASP Net sessions on a given IIS Website. See second file in the gist below, hopefully useful.

 

#Get the open requests being handled by IIS
$req = Get-WebRequest
while ($req.Count -gt 0)
{
#Wait if there are some
Write-Host "Waiting for request, current inflight: " $req.Count
Start-Sleep Seconds 2
#Check again for sessions
$req = Get-WebRequest
}
Write-Host "No Sessions on Box, lets update!"
## Do your stopping here, iisreset /stop etc

view raw
WaitForSessions.ps1
hosted with ❤ by GitHub

#WaitForSessionsAspNet.ps1
$ErrorActionPreference = "Stop"
#Used to get active sessions for a given set of app domains
function Get-ActiveConnections
{
Param(
[string[]]$instanceId
)
if (-not $instanceId)
{
throw "Instance ID required"
}
$results = $instanceId `
| %{ Get-Counter Counter "\asp.net applications($_)\sessions active" } `
| Select First 1 ExpandProperty CounterSamples `
| Measure-Object Property CookedValue Sum `
| Select ExpandProperty Sum
Write-Host "Aggregated value for active sessions: " $results
return $results
}
#Use to get the InstanceName for App Domains hosted in a particular website.
#N.B Relies on Get-Websites and Get-WebAppDomain commands which require the webadministration module to be installed.
function Get-PerfCounterInstanceNameForSite
{
Param(
[string]$siteName
)
if (-not $siteName)
{
throw "siteName required"
}
$website = Get-Website | where { $_.Name -eq $siteName }
if ($website.Length -ne 1)
{
throw "Failed to find site"
}
$appDomain = Get-WebAppDomain `
| where { $_.siteId -eq $website.id } `
| Select ExpandProperty id `
| ForEach-Object { $_ -replace "/", "_" } `
if ($appDomain.Length -lt 1)
{
Write-Host "App Domain for the site is not running, probably hasn't been hit recently by a request"
return $null
}
return $appDomain
}
#Script starts here
#Get instance names contained in the website. This is an array as one site can contain multiple app domains
$instanceIds = Get-PerfCounterInstanceNameForSite "Default Web Site"
#If there are no app domains for the site stop
if (-not $instanceIds)
{
Write-Host "App Domain isn't running for the site so there are no sessions"
return
}
#Get the number of active sessions for those app domain instances
$numberOfActiveSess = Get-ActiveConnections $instanceIds
#Loop while still active
while ($numberOfActiveSess -gt 0)
{
#Wait
Write-Host "Waiting for request, current inflight: " $numberOfActiveSess
Start-Sleep Seconds 10
#Update to see if session count has dropped
$numberOfActiveSess = Get-ActiveConnections $instanceIds
}
Write-Host "Requests Drained from Machine"

Standard

One thought on “Gracefully Drain Session from IIS Before Restarting/Stopping

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s