2011-05-24 36 views
1

我们有一个运行我们的应用程序的IIS 6服务器的Web场。
我们的会话存储在Sql Server 2005上的不同服务器上。

每隔几个月,我们都会在其中一个Web服务器日志中发现此错误: “Timeout expired。超时时间在从池中获取连接之前已过去,这可能是由于所有使用的池连接正在使用和最大池大小达到”Asp.Net中Session的问题

堆栈跟踪: System.Data.ProviderBase.DbConnectionInternal 的getConnection(System.Data.Common.DbConnection) 在 System.Data.ProviderBase.DbConnectionFactory.GetConnnection(的DbConnection 拥有连接)在 System.Data.ProviderBase。 DbConnectionClosed.OpenConnection(的DbConnection outerConnection,DbConnectionFactory connectionFactory的)在 System.Data.SqlClient.SqlConnection.Open() 在 Systme.Web.SessionState.SqlSessionStateStore.SqlStateConnection..ctor(SqlPartitionInfo sqlPartitionInfo)

当这个异常被抛出时,服务器开始表现得很奇怪 - 有些用户可以访问应用程序,有些则不会。

到目前为止,我们发现的唯一解决方案是重置该服务器上的IIS。

我也应该mantion服务器不appered被超载和preformence是非常正常的这种情况以前..

任何想法?

+0

除非您有一个非常具体的使用SQL的理由,否则您可以使用不带SQL的公共状态服务器,这会显着提高速度。 – 2011-05-24 06:42:03

+0

不幸的是,常见的状态服务器根本不会为大量用户剪切它,并且只能在Web场中使用粘性会话时才能使用。 – YsA 2011-05-24 07:51:49

+0

在我以前的工作中,我们有超过六百万用户,并且在多个Web和状态服务器上使用没有SQL的状态服务器没有问题。 – 2011-05-25 06:08:12

回答

5

这是资源管理不好的经典。 如果您正在使用SQL的自定义会话管理器(模块),那么您没有正确处理连接,并且应用程序池的连接不足。然后所有后续连接都在等待连接自动处理;这是超时发生的地方。

然而,这可能不是你的问题,所以你需要做的是限制的连接这样的超时时间:

超时重负载

下,如果你的网站 服务器负载很重,它可能是 对于增加会话状态访问的超时有用。您可以在web.config中 和machine.config中

的 stateNetworkTimeout属性添加到 的sessionState设置如果Web服务器或状态服务器 是在压力下,不能按时完成 会话访问,事件ID 1072并且在事件日志中可能会记录事件ID 1076 。

http://idunno.org/articles/277.aspx

此外 你应该只使用SessionState的基本数据类型,如字符串,整数,布尔 如果要存储的信息或复杂的数据类型很多,也许你需要reasses什么,为什么它存储在那里。

你应该看看使用缓存或视图状态。在互联网上有很多这样的文章,例如: http://www.codeproject.com/KB/session/exploresessionandcache.aspx

由于您的会话状态是基于SQL的,并且这是最慢的模式,所以您应该尽可能少地使用它。也许您可以使用唯一键将值存储在缓存中,并将唯一键存储在会话变量中。存在许多解决方法。

另一个更加有用的链接: http://devshop.wordpress.com/2008/04/10/how-to-choose-from-viewstate-sessionstate-cookies-and-cache/

0

因为您的评论变得更加具体,我也有以下的补充。如果你创建了以下一类:

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"); 
     } 
    } 

...然后在你的web.config你把类似如下:

<sessionState mode="StateServer" 
       partitionResolverType="NameSpaceName.PartitionResolver" 
       cookieless="false" 
       timeout="60" /> 

...然后按照说明进行操作:

http://www.c-sharpcorner.com/UploadFile/gopenath/Page107182007032219AM/Page1.aspx

...并在您的所有Web服务器上创建相同的机器密钥;那么你将不需要SQL会话状态,并且会有一个公共的会话状态,你可以在你需要的任何数量的状态服务器上进行负载平衡。

所有你将永远要做的就是更新这一行:

partitions = new String[] { "192.168.1.1", "192.168.1.2" }; // keep adding servers 

...你也应该有,所以即使出于某种原因,你切换Web服务器使用相同的状态服务器的多个Web服务器,你仍然会保持你的会话。而且,当您看到会话变慢时,请继续添加状态服务器。