TS Session Broker Extensibility (Part 2)

In a previous blog post, Christa gave a high level explanation of the extensibility points we introduced to Session Broker (SB) in Windows Server 2008. In this post, we will dive a bit deeper to see how we can use SB Extensibility to build our own load balancing logic.

As Christa mentioned, when a new incoming connection is received by a terminal server, the terminal server contacts the SB for directions on where to redirect this new user. To answer this question, the SB must go through its load balancing logic. Our implementation of this logic consists of:

  1. The SB looking through its database and picking the terminal server with the least number of sessions. (This is a slight simplification as the SB takes some other factors into account, but for now it is safe to ignore them for this discussion.)
  2. The SB then returns that information to the terminal server to which the user initially connected.
  3. The terminal server uses the returned data to execute the actual redirection.

Since the debut of Windows Server 2008, we’ve received some feedback regarding SB load balancing logic, labeling it too simplistic. While this may or may not be the case, with the extensibility points we’ve provided, you can fully replace the SB load logic with your own to load balance based on what might be important to you in your organization.

To implement your own load balancing logic and make use of these extensibility points, you will have to construct a COM server which implements the IWTSSBPlugin interface. This COM server (which I’ll refer to as an “extensibility plug-in”) will be called by the SB for passive notifications as well as requests to make load balancing decisions.

The IWTSSBPlugin interface has five methods which SB calls at different points. We will temporarily ignore WTSSBX_GetUserExternalSession and revisit it in a later blog post.

Let’s quickly review the four methods and when SB calls them:

· Initialize – called by SB when the SB service starts to allow the plug-in to do its initialization.

· Terminated – called by SB when the SB service shuts down to allow the plug-in to do its termination cleanup.

· WTSSBX_GetMostSuitableServer – called by SB when a load balancing decision needs to be made. We can use this method to override the SB’s default load balancing logic.

· WTSSBX_MachineChangeNotification – called by SB when a change occurs in one of the servers in the farm. We can use this method to get information on new terminal servers that have joined or left the farm.

· WTSSBX_SessionChangeNotification – called by SB when a change occurs in a session on a terminal server that is part of the farm. We can use this method to detect session state changes (such as when a user disconnects from his session).

The order in which these methods are called depends on what is happening in the farm. Let’s first look at the machine notifications:

When a server joins a farm the following notifications are called on the plug-in in the following order:

  1. WTSSBX_MachineChangeNotification is called with WTSSBX_NOTIFICATION_TYPE set to WTSSBX_NOTIFICATION_ADDED. This notification also provides the unique Machine ID which SB will use to identify this terminal server in all subsequent calls to the plug-in.
  2. WTSSBX_SessionChangeNotification is called with WTSSBX_NOTIFICATION_TYPE set to WTSSBX_NOTIFICATION_RESYNC. This notification reports the state of the sessions already existing on the terminal server joining the SB.
  3. WTSSBX_MachineChangeNotification is called with WTSSBX_NOTIFICATION_TYPE set to WTSSBX_NOTIFICATION_CHANGED. This notifies the plug-in that the terminal server is now part of the farm and is ready for incoming connections.

Similarly, when a server leaves the farm WTSSBX_MachineChangeNotification is called with WTSSBX_NOTIFICATION_TYPE set to WTSSBX_NOTIFICATION_REMOVED.

The session notifications are also quite simple:

These notifications provide the plug-in with enough information to make load balancing decisions.

The actual decisions are communicated to the SB via the WTSSBX_GetMostSuitableServer method. Let’s look back at the original explanation of how the SB load balancing logic is invoked to see where in that process WTSSBX_GetMostSuitableServer is called.

When a new connection comes to a terminal server, the server asks the SB to provide the Machine ID of the terminal server which has an existing session for the user. The SB queries its database and if no such session exists, the SB uses its standard load balancing logic to determine a Machine ID to which the user should be redirected. At this point, instead of returning this ID to the terminal server, the SB calls into the plug-in via the WTSSBX_GetMostSuitableServer method and passes the Machine ID it has just calculated as one of the parameters. The plug-in can then change this parameter to redirect to a different terminal server than the one originally intended.

So we see that by returning a different Machine ID in response to a WTSSBX_GetMostSuitableServer method call, we can override the default SB load balancing logic and provide our own.

In the next blog post, I will provide some design guidelines on how to construct your plug-in as well as an example of a plug-in that does resource-based load balancing.