【问题标题】:Find Reason for The wait operation timed out查找等待操作超时的原因
【发布时间】:2020-04-04 18:56:48
【问题描述】:

我有以下代码从数据库中获取数据。它托管在 WCF 服务(IIS 服务器)中。

public DataTable GetDocument(int DocumentID)
{
    SqlCommand sqlCommand = null;
    SqlConnection sqlConnection = null;
    SqlDataAdapter sqlDataAdapter = null;
    DataTable dataTable = null;

    try
    {
        sqlConnection = new SqlConnection();
        sqlConnection.ConnectionString = "Connection_String";

        sqlCommand = new SqlCommand();
        sqlCommand.CommandText = "dbo.[Get_Document]";
        sqlCommand.CommandType = CommandType.StoredProcedure;
        sqlCommand.Connection = sqlConnection;
        sqlCommand.Parameters.Add(new SqlParameter("@document_id", SqlDbType.BigInt, 8, ParameterDirection.Input, true, 19, 0, "", DataRowVersion.Proposed, DocumentID));

        sqlConnection.Open();

        sqlDataAdapter = new SqlDataAdapter(sqlCommand);
        dataTable = new DataTable("Document");
        sqlDataAdapter.Fill(dataTable);

        return dataTable;
    }
    catch (Exception ex)
    {
        ErrorLog.LogError(ex, "DocumentID = " + DocumentID);
    }
    finally
    {
        if (sqlConnection != null)
        {
            if(sqlConnection.State != ConnectionState.Closed)
                sqlConnection.Close();

            sqlConnection.Dispose();
            sqlConnection = null;
        }

        if (sqlCommand != null)
        {
            sqlCommand.Dispose();
            sqlCommand = null;
        }

        if (dataTable != null)
        {
            dataTable.Dispose();
            dataTable = null;
        }

        if (sqlDataAdapter != null)
        {
            sqlDataAdapter.Dispose();
            sqlDataAdapter = null;
        }
    }

    return null;
}

它工作正常,但随机出现以下超时异常。

PARAMETER : DocumentID =  987456

EXCEPTION

Error Message: Execution Timeout Expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.

Error Source: .Net SqlClient Data Provider

Error Stack Trace:    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
   at System.Data.SqlClient.SqlDataReader.get_MetaData()
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
   at System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior)
   at System.Data.Common.DbDataAdapter.Fill(DataTable dataTable)
   at DAL.DocumentController.GetDocument(int DocumentID)

TargetSite : Void OnError(System.Data.SqlClient.SqlException, Boolean, System.Action`1[System.Action])


INNER EXCEPTION

Error Message: The wait operation timed out


BASE EXCEPTION  

Error Message: The wait operation timed out

当发生超时异常时,我们使用适当的存储过程参数记录异常。稍后,当我们调查异常日志时,我们使用相同的参数执行相同的操作,但当时系统的行为符合预期(即使使用相同的参数也无法复制异常)。

据我所知,超时异常的原因有很多。我们已经设置了足够的超时时间,所以我们不想在我们的应用程序中增加超时时间。

我们只想知道在特定时间范围内发生超时异常的原因(例如,这是因为任何死锁、连接问题等)并记录了该原因,以便稍后我们可以按照正确的方向进行调查。

有没有办法知道超时异常的原因?

谢谢。

【问题讨论】:

  • 添加存储过程定义

标签: c# sql asp.net wcf ado.net


【解决方案1】:

我认为你是对的。超时异常可能是由于客户端请求量超过最大服务器负载或资源死锁。无论是 WCF 还是 SQL server 都存在并发请求限制。这是一个配置它的模板。

<behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="10000" maxConcurrentInstances="100" />
        </behavior>
      </serviceBehaviors>

实例化模式和并发模式会影响处理客户端请求的方式。
https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/sessions-instancing-and-concurrency
https://docs.microsoft.com/en-us/dotnet/api/system.servicemodel.servicebehaviorattribute.concurrencymode?view=netframework-4.8
实例化模式和并发模式的组合可能会导致死锁,从而导致超时异常。
最后,数据库连接字符串最好有单独的用户名/密码,因为IIS托管WCF应用程序的进程,会被替换为IIS应用程序池标识。

【讨论】:

    猜你喜欢
    • 2015-02-02
    • 1970-01-01
    • 1970-01-01
    • 2017-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-23
    相关资源
    最近更新 更多