2011-05-24 32 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服務器,你仍然會保持你的會話。而且,當您看到會話變慢時,請繼續添加狀態服務器。