Most web developers are familiar with one way with maintaining state within a web farm from their ASP days...server affinity. This was really the only optional available before .NET other than writing your own distributed session management solution for web applications if you wanted to maintain server side session state. This approach can also be used in the case of SCTs. Since most web services today are typically accessed via http, this logic is already built into load balancing hardware, and often these balancers will setup affinity for a particular service instance based on such values as client IP address or a cookie value, such as session ID. A common term used to describe this is "pinning" the session to a server instance. This may be a perfectly adequate solution for your service, and this is certainly the easiest option to implement. There is no additional development work required to implement this approach - typically just flip a switch in your load balancer, and your off to the races. The advantages of this approach are:
- Easiest to implement - no code required
- The most performant solution (assuming that it doesn't introduce significant load imbalance issues that are possible when pinning occurs)
- Simplest solution to support operationally
- Supports all base token types efficiently (more on this below)
The disadvantages of this solution are:
- Not resielent to server failures. Since the client is pinned to a particular instance, if the server goes down, the SCT is no longer valid. If the message subsequently gets rerouted to an available server, it will be rejected. This could be compensated for by logic in a smart client side proxy.
- Can introduce imbalances in loading - this is a typical problem with pinning a session to a particular instance
- Reliant upon some type of session affinity management. This is typical available with http load balancers, but may not be as likely of a feature for other load balancing solutions.
- This is a point-to-point approach. Messages transiting multiple hops won't have an http connection directly between the client and service.
One of the advantages mentioned above is supports all types of base tokens efficiently. The limitiation with the other two approaches mentioned that I will cover in the future is that they require the base token information to be serialized. Since the WSE SecurityToken class is not serialable, no derived class can not be serializable. There is an out...you should typically at least be able to retrieve the XML representation of a token with GetXml and LoadXml, but this adds significant additional memory and processing costs over binary serialization for the cached token. A technique to mitigate this cost that will be covered later is to cache the token locally. Therefore the deserialization only needs to occur if the token is not in the local cache - which means only once per token per service instance (assuming that the token doesn't get flushed from a full cache).
For a high reliability system, this approach would not be the best choice. While choosing the simplest solution that meets your needs is almost always the best choice, I am bothered by the fact that this relies on out-of-band information for session affinity and requires point to point communications that seesms to violate the spirit of messaging within SOA. But then I think maybe I'm being too much of a purist...
Tomorrow I'll start covering the distributed cache approach, where I'll start digging into some code samples.