Asp.Net中的会话问题
我们有一个运行我们的应用程序的IIS 6服务器的web服务器场。Asp.Net中的会话问题,asp.net,sql-server-2005,iis-6,session-state,Asp.net,Sql Server 2005,Iis 6,Session State,我们有一个运行我们的应用程序的IIS 6服务器的web服务器场。 我们的会话存储在不同服务器上的Sql Server 2005上。 每隔两个月,我们就会在其中一个web服务器日志中发现此错误: “超时已过期。从池中获取连接之前已过超时时间。这可能是因为使用了所有池连接,并且达到了最大池大小” 堆栈跟踪: System.Data.ProviderBase.DbConnectionInternal GetConnection(System.Data.Common.DbConnection) 在 Sy
我们的会话存储在不同服务器上的Sql Server 2005上。
每隔两个月,我们就会在其中一个web服务器日志中发现此错误: “超时已过期。从池中获取连接之前已过超时时间。这可能是因为使用了所有池连接,并且达到了最大池大小” 堆栈跟踪: System.Data.ProviderBase.DbConnectionInternal GetConnection(System.Data.Common.DbConnection) 在 System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection 拥有连接)位于 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection 外部连接,数据库连接工厂 连接工厂) System.Data.SqlClient.SqlConnection.Open() 在 Systme.Web.SessionState.SqlSessionStateStore.SqlStateConnection..ctor(SqlPartitionInfo sqlPartitionInfo) 当抛出此异常时,服务器开始表现出奇怪的行为-一些用户可以访问应用程序,而一些用户不可以 到目前为止,我们找到的唯一解决方案是在该服务器上重置IIS 我还应该保证,服务器似乎没有过载,在这种情况发生之前,性能相当正常
有什么想法吗?这是糟糕的资源管理的经典之作。 如果将自定义会话管理器(模块)与SQL一起使用,则未正确处理连接,并且应用程序池的连接正在耗尽。然后,所有后续连接都在等待自动处理该连接;这就是超时发生的地方 但是,这可能不是您的问题,因此您需要做的是限制连接的超时时间,如下所示: 重负载下超时 如果你的网站 服务器的负载可能很重 有助于增加的超时时间 会话状态访问。您可以添加 属性的stateNetworkTimeout属性 web.config中的会话状态设置 和machine.config 如果是Web服务器或状态服务器 处于压力之下,无法完成 会话按时访问,事件ID 1072和事件ID 1076可能会被记录 在事件日志中 此外 您应该只对基本数据类型(如string、int、bool)使用SessionState 如果要存储大量信息或复杂的数据类型,可能需要重新评估存储内容和存储原因 您应该研究如何使用缓存或Viewstate。互联网上有很多这样的文章,例如: 由于您的会话状态是基于SQL的,并且这是最慢的模式,因此您应该尽可能少地使用它。也许可以使用唯一键将值存储在缓存中,并将唯一键存储在会话变量中。存在许多变通办法 另一个更有用的链接:
这是糟糕的资源管理的经典之作。 如果将自定义会话管理器(模块)与SQL一起使用,则未正确处理连接,并且应用程序池的连接正在耗尽。然后,所有后续连接都在等待自动处理该连接;这就是超时发生的地方 但是,这可能不是您的问题,因此您需要做的是限制连接的超时时间,如下所示: 重负载下超时 如果你的网站 服务器的负载可能很重 有助于增加的超时时间 会话状态访问。您可以添加 属性的stateNetworkTimeout属性 web.config中的会话状态设置 和machine.config 如果是Web服务器或状态服务器 处于压力之下,无法完成 会话按时访问,事件ID 1072和事件ID 1076可能会被记录 在事件日志中 此外 您应该只对基本数据类型(如string、int、bool)使用SessionState 如果要存储大量信息或复杂的数据类型,可能需要重新评估存储内容和存储原因 您应该研究如何使用缓存或Viewstate。互联网上有很多这样的文章,例如: 由于您的会话状态是基于SQL的,并且这是最慢的模式,因此您应该尽可能少地使用它。也许可以使用唯一键将值存储在缓存中,并将唯一键存储在会话变量中。存在许多变通办法 另一个更有用的链接:
随着您的评论变得更加具体,我还要补充以下内容。如果创建如下所示的类:
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");
}
}
<sessionState mode="StateServer"
partitionResolverType="NameSpaceName.PartitionResolver"
cookieless="false"
timeout="60" />
。。。然后在web.config中放入如下内容:
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");
}
}
<sessionState mode="StateServer"
partitionResolverType="NameSpaceName.PartitionResolver"
cookieless="false"
timeout="60" />
。。。您可以有多个web服务器使用相同的状态服务器,因此即使出于任何原因切换web服务器,您仍然可以维护会话。而且,当您看到会话速度减慢时,只需继续添加状态服务器。随着您的评论变得更加具体,我还需要添加以下内容。如果创建如下所示的类:
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");
}
}
<sessionState mode="StateServer"
partitionResolverType="NameSpaceName.PartitionResolver"
cookieless="false"
timeout="60" />
。。。然后在web.config中放入如下内容:
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");
}
}
<sessionState mode="StateServer"
partitionResolverType="NameSpaceName.PartitionResolver"
cookieless="false"
timeout="60" />
。。。您可以有多个web服务器使用相同的状态服务器,因此即使出于任何原因切换web服务器,您仍然可以维护会话。而且,当您看到会话速度变慢时,只需继续添加状态服务器。除非您有非常具体的理由使用SQL,否则您可以使用没有SQL的公共状态服务器,这会明显加快速度。不幸的是,公共状态服务器根本无法为大量用户提供服务,只有在web服务器场中使用sticky会话时,它才能工作。在我以前的工作中,我们有600多万用户,跨多个web和状态服务器使用不带SQL的状态服务器没有问题。事实上:除非您有非常具体的理由使用SQL,否则您可以使用不带SQL的公共状态服务器,这将非常明显