Sunday, September 21, 2008

Using state server with ASP.NET

At work we deal a lot with the web version of SuperOffice CRM, and lately I've been trying to figure out why one of our customers users keep getting logged out all the time. Through a dialog with the core technical persons at SuperOffice we've tracked it down to the Session being lost.



Most likely the session is lost because the Application Pool is recycled for some reason. There are several thing which could cause such a recycle.
- web.config being changed
- files in \bin or \App_code directories are modified
- any of the conditions in Process Model for the Application Pool is met. Like a memory limit being hit, or a request-queue being full.
- antivirus or similar modifying the above files

Because of all of this I've researched what it takes to move the session state handling out of the w3wp.exe process, and it's actually not that difficult.

Session state can primarily be handled in three ways. In-Process, with State server or in SQL server. There is also a Custom way, but that's out of our scope for now.

Moving from In-process to using the State server is as easy as modifying a single line in your web.config, and making sure the Windows Service called ASP.NET State Service is running. The web.config should include a sessionState element, like this.

<configuration>
<system.web>
<sessionState mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424"
cookieless="false"
timeout="20">
</sessionstate>
</system.web>

And that's it!

What we've gained by doing this is that the changes listed above will no longer cause a user to be logged out. You can even call iireset.exe, and the session is still kept alive. What we've lost is about 15% performance since the session needs to be serialized out from the w3wp.exe process, and handled by the aspnet_state.exe process.

If the ASP.NET State Service is restarted it will loose all the sessions since they are kept in-memory by the service.

We can also take this one step further by storing the sessions in a SQL database instead. By doing this we gain even more recilience because we can reboot the server which handles the sessions, and users are still maintaining their sessions when the server is online again.

In order to set up SQL handling of the sessions you'll need to modify the web.config again, but also have a SQL database to store the sessions in.

<system.web>
<configuration>
<sessionState mode="SQLServer"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString= "data source=127.0.0.1;
user id=sa;password=secret"
cookieless="false"
timeout="20">
</sessionstate>
</system.web>
</configuration>


And the SQL database is created by a tool that ships with the .NET Framework.

C:\>aspnet_regsql.exe -S localhost -U sa -P secret -ssadd -sstype p

That command will create a database on the local SQL server called ASPState where all the sessions are stored. The drawback of storing sessions in SQL is that you loose about 25% performance compared to the InProc mode.

Saturday, September 6, 2008

Cosmos is expanding

I've been putting down a lot of time working on the Cosmos project over the last few months, and it's fun to see all the progress we've been making.

The network driver for the RTL is complete enough to send and receive the data we want, and currently further development for RTL and UDP is continued by Chad Hower (here and here).

I've moved over to filesystem, and am working with the Virtual Filesystem layer. Currently it's working on top of the Ext2 filesystem, but the purpose of this layer is to be filesystem independent. We can enumerate directories and files using classes in the System.IO namespace, but I haven't begun to read inside files yet. For that we are going to need support for Streams.

Often during the development I come across certain basic parts of the .NET framework which break our build, so I keep going back to the absolute basics to fix those as well. As an example I added lots of Console.Write and Console.WriteLine overloads, since we were unable to print lots of basic types. Today I fixed Boolean.Parse(string) and Boolean.TryParse(string, out bool).

I believe it's important to get all this basic functionality in place as well, not just features like network, filesystem and compilation speed. It'll be a lot easier for newcomers to get started if we have all the basics in place.