Using ARR config extensibility to gracefully stop server

Now that Application Request Router v2 is out and I have a bit more time for other stuff, I thought I would write about the config extensibility offered by ARR.  The below example applies for both v1 and v2.  Note that using AHAdmin via JScript is the config interface I am most familiar with, but you can easily convert this sample to either PowerShell or MWA.

The below first issues a graceful stop to the server using a dynamic method and then monitors the number of outstanding requests, waiting until it falls to 0 and deletes the server from configuration at that point.  If the number of active sessions rather than requests is what you look at (for apps with persistent sessions) for removing your servers from rotation, you can change state to “Drain” and then using performance counters to obtain outstanding session information from the remote server and using that to decide when to remove the server from rotation.  For other dynamic methods/properties provided by ARR, look at the schema at %windir%\system32\inetsrv\config\schema\arr_schema.xml.

Let me know if you would like to see sample usage for other ARR config extensibility points.

   1:  if (WScript.Arguments.length != 2)
   2:  {
   3:      WScript.Echo("Usage: stop_server.js <webfarm name> <server name>");
   4:      WScript.Quit(-1);
   5:  }
   6:   
   7:  var ahAdmin = new ActiveXObject("Microsoft.ApplicationHost.WritableAdminManager");
   8:  ahAdmin.CommitPath = "MACHINE/WEBROOT/APPHOST";
   9:  var arrSection = ahAdmin.GetAdminSection("webFarms", "MACHINE/WEBROOT/APPHOST");
  10:  var farmCollection = arrSection.Collection;
  11:  for (var i=0; i<farmCollection.Count; i++)
  12:  {
  13:    var farm = farmCollection.Item(i);
  14:    if (farm.GetPropertyByName("name").Value != WScript.Arguments(0))
  15:    {
  16:      continue;
  17:    }
  18:    WScript.Echo("Found webfarm " + WScript.Arguments(0));
  19:   
  20:    var serverCollection = farm.Collection;
  21:    for (var j=0; j<serverCollection.Count; j++)
  22:    {
  23:      var server = serverCollection.Item(j);
  24:      if (server.GetPropertyByName("address").Value != WScript.Arguments(1))
  25:      {
  26:        continue;
  27:      }
  28:      WScript.Echo("Found server " + WScript.Arguments(1));
  29:   
  30:      var arrElement = server.GetElementByName("applicationRequestRouting");
  31:      var method = arrElement.Methods.Item("SetState");
  32:      var methodInstance = method.CreateInstance();
  33:      var property = methodInstance.Input.GetPropertyByName("newState");
  34:      property.Value = "GracefulStop";
  35:      try
  36:      {
  37:        methodInstance.Execute();
  38:        WScript.Echo("Stop issued");
  39:      }
  40:      catch (e)
  41:      {}
  42:   
  43:      while (true)
  44:      {
  45:        var counters = arrElement.GetElementByName("counters");
  46:        var currRequests = 0;
  47:        try
  48:        {
  49:          currRequests = counters.GetPropertyByName("currentRequests").Value;
  50:        }
  51:        catch(e)
  52:        {}
  53:   
  54:        if (currRequests == 0)
  55:        {
  56:          WScript.Echo("All requests finished - deleting server");
  57:          serverCollection.DeleteElement(j);
  58:          ahAdmin.CommitChanges();
  59:          WScript.Quit();
  60:        }
  61:        WScript.Echo("Currently executing requests: " + currRequests);
  62:      }
  63:    }
  64:   
  65:    break;
  66:  }

No Comments