Problems with Session in Asp.Net
We have a web farm of IIS 6 servers that runs our application.
Our session is stored on Sql Server 2005 on a diffrent server.
Every couple of months we are getting this error in one of the web server logs:
"T开发者_Go百科imeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred beacuse all the pooled connections were is use and max pool size was reached"
Stack trace: System.Data.ProviderBase.DbConnectionInternal GetConnection(System.Data.Common.DbConnection) at System.Data.ProviderBase.DbConnectionFactory.GetConnnection(DbConnection owningConnection) at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection,DbConnectionFactory connectionFactory) at System.Data.SqlClient.SqlConnection.Open() at Systme.Web.SessionState.SqlSessionStateStore.SqlStateConnection..ctor(SqlPartitionInfo sqlPartitionInfo)
When this exception is thrown the server starts to behave strange - some users can access the app and some do not.
The only solution we found so far is to reset IIS on that server.
I should also mantion that the server is not appered to be overloading and the preformence is pretty normal before this happens..
Any ideas?
This is classic of bad resource management. If you are using a custom Session Manager (module) with SQL then you are not disposing of the connections properly, and the application pool is running out of connections. Then all subsequent connection are waiting for the connection to automatically be disposed; and this is where the timeout occurs.
However, this is probably not your problem, so what you need to do is limit the timeout time of the connections as such:
Timeouts under heavy load
If your web servers are under heavy load it may be useful to increase the time out for session state access. You can add the stateNetworkTimeout attribute to the sessionState settings in web.config and machine.config
If a Web server or a state server is under stress and cannot complete session accesses on time, event ID 1072 and event ID 1076 may be logged in the event log.
http://idunno.org/articles/277.aspx
Furthermore You should only use SessionState for basic data types like string, int, bool If you are storing alot of information or complex data types, maybe you need to reasses what and why it is stored there.
You should look into using Cache or Viewstate. There are many such articles on the internet, for example: http://www.codeproject.com/KB/session/exploresessionandcache.aspx
Since your session state is SQL based, and this is the slowest mode, you should really try to use it as least as possible. Maybe you could store values in the cache with a unique key, and store the unique key in the session variable. Many workarounds exist.
Another more useful link: http://devshop.wordpress.com/2008/04/10/how-to-choose-from-viewstate-sessionstate-cookies-and-cache/
As your comments became more specific, I also have the following to add. If you create a class like the following:
public class PartitionResolver : System.Web.IPartitionResolver
{
private String[] partitions;
public void Initialize()
{
// create the partition connection string table
// web1, web2
partitions = new String[] { "192.168.1.1", "192.168.1.2" }; // keep adding servers
}
public String ResolvePartition(Object key)
{
String oHost = System.Web.HttpContext.Current.Request.Url.Host.ToLower().Trim();
if (oHost.StartsWith("10.0.0") || oHost.Equals("localhost"))
return "tcpip=127.0.0.1:42424";
String sid = (String)key;
// hash the incoming session ID into
// one of the available partitions
Int32 partitionID = Math.Abs(sid.GetHashCode()) % partitions.Length;
return ("tcpip=" + partitions[partitionID] + ":42424");
}
}
... and then in your web.config you put something like the following:
<sessionState mode="StateServer"
partitionResolverType="NameSpaceName.PartitionResolver"
cookieless="false"
timeout="60" />
... and then follow the instructions:
http://www.c-sharpcorner.com/UploadFile/gopenath/Page107182007032219AM/Page1.aspx
... and create an identical machine key across all your web servers; then you will not require SQL session state, and will have a common session state, which you can load balance across any number of state servers that you may require.
All you would ever have to do is update this line:
partitions = new String[] { "192.168.1.1", "192.168.1.2" }; // keep adding servers
... and you could have multiple web servers using the same state servers, so even if for whatever reason you switch web servers, you will still maintain your session. And also, as you see the session slowing down, just keep adding state servers.
精彩评论