Иногда мы сталкиваемся с подобными исключениями в нашем приложении WebApi с Oracle Poolmanager:
à 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 securedPassword, SecureString securedProxyPassword, CriteriaCtx attributeCtx) à Oracle.ManagedDataAccess.Client.OracleConnection.Open ()
Эта проблема воспроизводится с использованием ODP.Net 2.2 в сети 4.5.1 и .net core 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}";
});
}
Как видите, вызов метода ParallelConnectionс 20 соединениями установите 4 первых потока в Timeout по умолчанию на 15 секунд, и время соединения других потоков не является разумным!Обычный обходной путь, найденный в Интернете, заключается в увеличении времени ожидания соединения, но в нашем случае время отклика нашего веб-API не является разумным.
Может ли кто-нибудь объяснить, почему открытие первого соединения в ODP.Net требует такого огромноговремя в многопоточности?Есть ли способ избежать этого исключения тайм-аута соединения в приложении Web Api?