查找原因,等待操作超时

时间:2019-12-11 13:17:53

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

我有以下代码从数据库获取数据。它托管在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

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

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

我们只想知道超时异常的原因,为什么会在特定时间范围内发生(例如,由于任何死锁,连接问题等),并记录该原因,因此稍后我们可以进行正确的研究。

有什么办法可以知道超时异常的原因吗?

谢谢。

1 个答案:

答案 0 :(得分:0)

我认为你是对的。超时异常可能是由于客户端请求量超过最大服务器负载或资源死锁所致。无论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
实例化模式和并发模式的组合可能会导致死锁,从而导致超时异常。
最后,数据库连接字符串最好使用单独的用户名/密码,因为承载WCF应用程序的IIS进程将被IIS应用程序池标识代替。