asp.net - 超时已过。在从池中获取连接之前超时时间已过。企业图书馆

标签 asp.net wcf timeout connection-pooling enterprise-library

我的 ASP.NET 4.0 生产应用程序再次出现问题,导致站点由于超时错误而无响应。

以下是该应用程序的简要概述。该应用程序驻留在 3 台服务器上;一个 Web 服务器、一个应用服务器和一个运行 SQL Server 2008 的数据库服务器。所有服务器都在 Windows Server 2008 上运行。Web 服务器位于公共(public)域中。应用服务器驻留在 DMZ 中,Web 服务器之间通过 WCF 通过端口 80 和 443 进行开放式通信。数据库服务器位于一个私有(private)域中,通过端口 1433 与应用程序服务器进行开放通信。该应用程序已经投入生产一段时间了,直到上周才经常遇到这些问题。没有代码更改,托管服务提供商表示最近没有对服务器进行任何更改。

在 Web 服务器上,应用程序遇到下面发布的错误(错误 1)。快速修复的解决方案是重新启动应用服务器 IIS 进程,但是,现在这是一个反复出现的问题,并对企业所有者造成重大干扰。

应用程序的 DAL 使用 Enterprise Library v4.1 打开与数据库的连接。我已经包含了 2 个负责启动调用的代码片段(代码 1 和代码 2)。这种方法在各种其他方法中重复。 ExecuteReader 方法是否可能没有正确关闭连接?没有覆盖允许我指定 ConnectionBehavior 以关闭连接的方法。

我们执行了 SQL 配置文件分析,并确定没有到数据库的开放连接。

在研究该问题时,有人建议 Enterprise Library 可能存在连接未正确处理的错误,但未在帖子中对此进行验证。如何确定问题的原因?或者解决问题的适当行动方案是什么?我可以增加池大小,但这似乎只是一个临时解决方案。

错误 1:

***System.ServiceModel.FaultException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached. at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) at System.Data.SqlClient.SqlConnection.Open() at Microsoft.Practices.EnterpriseLibrary.Data.Database.GetNewOpenConnection() at Microsoft.Practices.EnterpriseLibrary.Data.Database.GetOpenConnection(Boolean disposeInnerConnection) at Microsoft.Practices.EnterpriseLibrary.Data.Database.ExecuteReader(DbCommand command) at Microsoft.Practices.EnterpriseLibrary.Data.Database.ExecuteReader(String storedProcedureName, Object[] parameterValues) at CityStoreDAL.NavigationProvider.GetNavigator(Int32 navigatorID) in c:\TFS\CityStore\DEV\SRC\CityStoreDAL\NavigationProvider.cs:line 41 at CityStoreBLL.Navigation.GetNavigator(Int32 navigatorID) in c:\TFS\CityStore\DEV\SRC\CityStoreBLL\Navigation.cs:line 15 at CityStoreService.CityStoreService.GetNavigator(Int32 navigato rID) in c:\TFS\CityStore\DEV\SRC\CityStoreService\Navigation.cs:line 21 at SyncInvokeGetNavigator(Object , Object[] , Object[] ) at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)***
Generated: Wed, 12 Nov 2014 19:40:22 GMT

System.Web.HttpUnhandledException: Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.ServiceModel.FaultException: Timeout expired.  The timeout period elapsed prior to obtaining a connection from the pool.  This may have occurred because all pooled connections were in use and max pool size was reached.   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()
   at Microsoft.Practices.EnterpriseLibrary.Data.Database.GetNewOpenConnection()
   at Microsoft.Practices.EnterpriseLibrary.Data.Database.GetOpenConnection(Boolean disposeInnerConnection)
   at Microsoft.Practices.EnterpriseLibrary.Data.Database.ExecuteReader(DbCommand command)
   at Microsoft.Practices.EnterpriseLibrary.Data.Database.ExecuteReader(String storedProcedureName, Object[] parameterValues)
   at CityStoreDAL.NavigationProvider.GetNavigator(Int32 navigatorID) in c:\TFS\CityStore\DEV\SRC\CityStoreDAL\NavigationProvider.cs:line 41
   at CityStoreBLL.Navigation.GetNavigator(Int32 navigatorID) in c:\TFS\CityStore\DEV\SRC\CityStoreBLL\Navigation.cs:line 15
   at CityStoreService.CityStoreService.GetNavigator(Int32 navigatorID) in c:\TFS\CityStore\DEV\SRC\CityStoreService\Navigation.cs:line 21
   at SyncInvokeGetNavigator(Object , Object[] , Object[] )
   at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

Server stack trace: 
   at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at CityStoreWeb.CityStoreServiceReference.INavigation.GetNavigator(Int32 navigatorID)
   at CityStoreWeb.Product.<>c__DisplayClass1.<BindCategoryMenuAndInfo>b__0(INavigation proxy) in c:\TFS\CityStore\DEV\SRC\CityStoreWeb\Product.aspx.cs:line 73
   at CityStoreWeb.Common.Service'1.Use(UseServiceDelegate'1 codeBlock) in c:\TFS\CityStore\DEV\SRC\CityStoreWeb\Common\Utils.cs:line 243
   at CityStoreWeb.Product.BindCategoryMenuAndInfo(Int32 navigatorID) in c:\TFS\CityStore\DEV\SRC\CityStoreWeb\Product.aspx.cs:line 71
   at CityStoreWeb.Product.SetupPage(Int32 navigatorID, Int32 categoryID, Int32 productID) in c:\TFS\CityStore\DEV\SRC\CityStoreWeb\Product.aspx.cs:line 64
   at CityStoreWeb.Product.Page_Load(Object sender, EventArgs e) in c:\TFS\CityStore\DEV\SRC\CityStoreWeb\Product.aspx.cs:line 37
   at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
   at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
   at System.Web.UI.Control.OnLoad(EventArgs e)
   at CityStoreWeb.Common.BasePage.OnLoad(EventArgs e) in c:\TFS\CityStore\DEV\SRC\CityStoreWeb\Common\BasePage.cs:line 26
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   --- End of inner exception stack trace ---
   at System.Web.UI.Page.HandleError(Exception e)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest()
   at System.Web.UI.Page.ProcessRequest(HttpContext context)
   at ASP.product_aspx.ProcessRequest(HttpContext context)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

代码1:
public static NavigatorEntity GetNavigator(int navigatorID)
{
        Database db = DatabaseFactory.CreateDatabase();
        object[] spParams;
        spParams = new object[1];
        spParams[0] = navigatorID;
        using (IDataReader reader = db.ExecuteReader("GetNavigator", spParams))
        {
            if (reader == null)k
            {
                throw new ArgumentNullException("reader");
            }
            NavigatorEntity myNav = null;
            if (reader.Read())
            {
                myNav = GetNavigatorEntityFromReader(reader);
            }

            if (myNav != null)
            {
                reader.NextResult();
                myNav.Categories = GetCategoriesCollectionFromReader(reader);

                reader.NextResult();
                myNav.RecommendedProducts = 
                    ProductProvider.GetRecommendedProductCollectionFromReader(reader, false);
            }

            return myNav;
        }
    }

代码 2:
public static List<NavigatorEntity> GetNavigatorsAll()
{
    Database db = DatabaseFactory.CreateDatabase();

    using (IDataReader myReader = db.ExecuteReader("GetNavigatorsAll"))
    {
        return GetNavigatorCollectionFromReader(myReader);
    }
}

private static List<NavigatorEntity> GetNavigatorCollectionFromReader(IDataReader reader)
{
    List<NavigatorEntity> navigators = new List<NavigatorEntity>();
    while (reader.Read())
    {
        navigators.Add(GetNavigatorEntityFromReader(reader));
    }
    return navigators;
}

更新:

显然,问题不在于 ASP.NET 错误中引用的任何方法。他们抛出异常是因为在到达时,问题(连接池耗尽)已经发生,并且在打开新连接的任何继续方法上都会抛出异常。

在分析了数据访问层中的所有代码之后,我发现了一些没有正确使用 using 语句的 rouge 方法,从而导致池中的开放连接累积起来。在隔离这些方法并使用性能监视器观察 NumberOfPooledConnections 之后,我确认这些方法是罪魁祸首。

解决方法是将 rouge 方法包装在适当的 using 语句中。

导致问题的方法之一:
public static List<TaxCodeEntity> CMSGetTaxCodes()
{
    Database db = DatabaseFactory.CreateDatabase();
    return GetTaxCodeCollectionFromReader(db.ExecuteReader("CMS_GetTaxCodes"));            
}

修复:
public static List<TaxCodeEntity> CMSGetTaxCodes()
{
    Database db = DatabaseFactory.CreateDatabase();
    using (DbCommand dbCmd = db.GetStoredProcCommand("CMS_GetTaxCodes"))
    {
        using (IDataReader myReader = db.ExecuteReader(dbCmd))
        {
            return GetTaxCodeCollectionFromReader(myReader);
        }    
    }
}

最佳答案

阅读器打开后,我可以看到许多操作发生。如果在依赖函数上引发任何异常,例如: myNav.Categories = GetCategoriesCollectionFromReader(reader);可以保持阅读器打开。安全侧专门关闭阅读器。像这样:

    public static NavigatorEntity GetNavigator(int navigatorID)
    {
        Database db = DatabaseFactory.CreateDatabase();
        object[] spParams;
        spParams = new object[1];
        spParams[0] = navigatorID;
        using (IDataReader reader = db.ExecuteReader("GetNavigator", spParams))
        {
            try
            {
                if (reader == null)
                {
                    throw new ArgumentNullException("reader");
                }
                NavigatorEntity myNav = null;
                if (reader.Read())
                {
                    myNav = GetNavigatorEntityFromReader(reader);
                }

                if (myNav != null)
                {
                    reader.NextResult();
                    myNav.Categories = GetCategoriesCollectionFromReader(reader);

                    reader.NextResult();
                    myNav.RecommendedProducts = 
                        ProductProvider.GetRecommendedProductCollectionFromReader(reader, false);
                }

                return myNav;
            }
            catch
            {
            }
            finally
            {
                reader.Close();
            }
        }
    }

还要留意你的 sql server:

SELECT DB_NAME(dbid), COUNT(dbid), loginame from sys.sysprocesses where dbid > 0
GROUP BY dbid, 登录名

关于asp.net - 超时已过。在从池中获取连接之前超时时间已过。企业图书馆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26982185/

相关文章:

c# - 链接的 .CS 文件和 WCF 服务的引用不明确

java - 在 Java 中停止阻塞套接字

c# - foreach 的分支覆盖?

c# - 系统参数异常 : Invalid postback or callback argument

.net - 使用传输安全和证书的 WCF 服务出现 SSL 错误。验证

c# - WCF 协议(protocol)异常

java - Tomcat 请求因超时而取消

java - Android 的 HttpResponse 和超时

asp.net - 控制台应用程序托管 ASPX 页面?

c# - 如何调试包含 ASP classic、ASP.NET、C# 和 VB 的项目?