Oracle Data Provider for .NET:多线程连接请求超时

时间:2019-03-15 08:55:03

标签: c# oracle .net-core .net-4.5 odp.net

有时,在使用Oracle Poolmanager的WebApi应用程序上遇到类似这样的异常:

  

àOracleInternal.ConnectionPool.PoolManager 3.Get(ConnectionString csWithDiffOrNewPwd, Boolean bGetForApp, CriteriaCtx criteriaCtx, String affinityInstanceName, Boolean bForceMatch) à OracleInternal.ConnectionPool.OraclePoolManager.Get(ConnectionString csWithNewPassword, Boolean bGetForApp, CriteriaCtx criteriaCtx, String affinityInstanceName, Boolean bForceMatch) à OracleInternal.ConnectionPool.OracleConnectionDispenser 3.Get(ConnectionString cs,PM conPM,ConnectionString pmCS,SecureString securePassword,SecureString secureProxyPassword,CriteriaCtx条件Ctx)      àOracle.ManagedDataAccess.Client.OracleConnection.Open()

使用net 4.5.1和.net core 2.2中的ODP.Net 2.2可以重现此问题。

以下是重现它的示例代码:

 private static void ParallelConnection(int nbConnection, string connectionString)
    {
        var watch = Stopwatch.StartNew();
        Console.WriteLine($"Testing {nbConnection} Connections");
        var taskList = new List<Task<string>>();
        for (int i = 0; i < nbConnection; i++)
        {
            taskList.Add(OpenConnectionSimple(i + 1, connectionString));
        }
        Task.WaitAll(taskList.ToArray());
        taskList.ForEach(t => Console.WriteLine(t.Result));
        Console.WriteLine($"Total elapsed {watch.ElapsedMilliseconds}");
        Console.ReadLine();
    }

private static async Task<string> OpenConnectionSimple(int index, string connectionString)
    {
        return await Task<string>.Factory.StartNew(() =>
        {
            var error = string.Empty;
            var startTime = DateTime.Now;
            var watch = Stopwatch.StartNew();
            var date = DateTime.MinValue;
            long timeCreated = -1;
            long timeOpen = -1;
            try
            {
                using (var cnx = new OracleConnection(connectionString))
                {
                    timeCreated = watch.ElapsedMilliseconds;
                    cnx.Open();
                    timeOpen = watch.ElapsedMilliseconds;
                    using (var cmd = cnx.CreateCommand())
                    {
                        cmd.CommandType = System.Data.CommandType.Text;
                        cmd.CommandText = "SELECT SYSDATE FROM DUAL";
                        date = (DateTime)cmd.ExecuteScalar();
                    }
                }
            }
            catch (Exception ex)
            {
                error = ex.Message;
            }
            watch.Stop();
            var state = (string.IsNullOrWhiteSpace(error)) ? "OK" : $"KO :{error}";
            return $"[{index}]\t start: {startTime:HH:mm:ss.fff}  duration:{watch.ElapsedMilliseconds}ms\t Ctor Connection:{timeCreated}ms \t open Connection:{timeOpen}ms \t SYSDATE Oracle: {date}\t State:{state}";
        });
    }

Result execution

如您所见,调用具有20个连接的ParallelConnection方法会使Timeout中的第四个线程在默认情况下超过15秒,而其他线程的连接时间并不合理! 在网络上发现的常见解决方法是使连接超时更大,但在我们这种情况下,Web api的响应时间并不合理。

有人可以解释为什么在ODP.Net中打开第一个连接会在多线程中花费大量时间吗? 是否有解决方法来避免Web Api应用程序中的此连接超时异常?

0 个答案:

没有答案