Sessions and State
Consider the issue of stateful vs. stateless IIS applications. When you create an IIS application, you can set the StateManagement property to wcNoState or wcRetainInstance. When you specify wcRetainInstance, the Webclass object continues to exist for the duration of the ASP session. How long is a session? ASP typically discards a session if a user has not accessed the site in 10 minutes. The idea and implementation of a session is part of Microsoft's Internet Information Server (IIS). You see, HTTP is a stateless protocol - meaning that each connection is completely independent of the next. Microsoft's IIS sends a cookie that identifies a session to the browser the first time it accesses an application. It uses this cookie to recognize who the user is during subsequent connections to the same application.
Let's say that you have a site that needs to handle 1000 users/hour and your state management is set to wcRetainInstance. Note that this is not the same thing as 1000 site hits or connections per hour. Static pages on a site do not use sessions because they are not part of your application, and each user can have multiple connections during their session. Assume that your application does not manually terminate sessions. Those 1000 users will each have a 10 minute session, meaning that your average number of concurrent sessions is 1000 / 6 = 167. That means that your server will have an average of 167 webclass objects open at all times on your site. That's a fairly large number of objects, though probably still manageable on a fast server.
What happens when you change your application to be stateless?
In this case, the webclass objects only exist during a connection. Let's assume that each user can perform two connections per minute. If we look at the typical state of the server during a one minute period, we'll see 34 connections per minute. Based on this, the average number of webclass objects that exist during any given minute will be 34.At first glance, this suggests that there is an overwhelming advantage to using a stateless approach, but this is not necessarily the case. First, creating a stateless object is more difficult than creating a stateful object because you must somehow save all of the necessary information for the object between connections. Next, overhead is involved in saving and restoring the object data during each connection.
Why then, should you consider the stateless approach?
Because the 167 object number that we came up with in the first example represents not the worst case, but a minimal number of concurrent objects that must be maintained for the conditions described in the scenario. The objects remain present even if the user does nothing for 10 minutes. But in the stateless scenario, what happens when a user takes two minutes between connections instead of 30 seconds? The average number of connections during a given minute drops less than 9! Is this realistic? Next time you purchase something on the Internet, calculate how long it takes for you to go through each page in the purchasing process. I think you'll find that two minutes is not an unusual amount of time to spend on a page. And let's face it, with today's fast machines, it doesn't take too much power to support 9 connections per minute.
How do these approaches scale at 10000 users/hour?
The stateful approach increases to managing 1670 webclass objects is quite a substantial hit. The stateless approach increases to 90.
Now consider our earlier discussion on scalability. If you can actually support 10,000 user/hour with a stateless IIS application on a single server, do you really need to consider more complex approaches? If you are developing a large scale online destination, then your number of users will be far greater and the answer is yes. But if you're a small to medium sized business with a specialty application, the added development time and the resources needed to build a larger site may be money wasted.
There is, of course, one catch to this discussion. The numbers are still hypothetical and depend greatly on the type of application you are developing.
Stateless Applications and Object Storage
The argument for going with a stateless approach is compelling, but it does impose new design challenges. You still need a way to preserve your applications state between connections. There are a number of approaches that you can use:
Store state information in cookies
Store state information in the pages
Store state information in an external database or data file
Store information in the ASP Session object
Let's look at these approaches one at a time:
Store state information in cookies
This is not a bad approach for simple information. Cookies are sent on each request, so you don't want to load the browser with large blocks of data.
Store state information in the pages
IIS Applications have the ability to dynamically generate and modify the pages that they send to the user. The URLData features allows arbitrary text to be included in the page that will be sent back with the URL during subsequent requests. One advantage of this approach is that it even works with browsers that have cookie support disabled. One disadvantage is that the amount of text you can include in a URLData line is limited.
Store state information in an external database or data file
In this approach you use a single cookie that acts as a key into a database or file. The data file contains the stored information. This approach has the advantage of allowing you to store as much data as you need without wasting bandwidth sending it back and forth as cookies. There is, however, a performance cost due to the need to access the data from an external file on each connection.
Store information in the ASP Session object
The ASP system includes a Session object in which you can store arbitrary data in named fields. There are two types of data with which to be concerned. String, numeric and binary data is easy to store and has minimal impact on system performance. You can also store objects in the Session Object. However, storing objects has two disadvantages:
- You lose some of the benefit that you gained by making your application stateless. Now, instead of storing the webclass object for the duration of the session, you're storing a different object.
- Storing objects in session variables can have a serious performance impact. If the object is apartment model threaded (as is the case with VB objects), storing an object in the Session variable locks the session to a single thread. Thus you lose the potential benefits of multithreading for that session.
You can, however, develop a combination approach thanks to Visual Basic's new support for creating self-persisting objects. Define your object to use a PropertyBag to save its state. At the end of a connection (the webclass EndRequest event), store your internal objects into a PropertyBag, and save the binary data in the Session object. During the next connection (the webclass BeginRequest event), retrieve the binary data from the Session object and store it in a PropertyBag. Then reload your objects from the PropertyBag. This approach is slightly less efficient in terms of performance (it does take time to save and load data from PropertyBags), but avoids locking the session down to a single thread. You can also combine these approaches in other ways. For example: instead of storing the object data from the PropertyBag in a Session object, you can store it in an external data file that is indexed by a cookie.