有时,在使用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}";
});
}
如您所见,调用具有20个连接的ParallelConnection方法会使Timeout中的第四个线程在默认情况下超过15秒,而其他线程的连接时间并不合理! 在网络上发现的常见解决方法是使连接超时更大,但在我们这种情况下,Web api的响应时间并不合理。
有人可以解释为什么在ODP.Net中打开第一个连接会在多线程中花费大量时间吗? 是否有解决方法来避免Web Api应用程序中的此连接超时异常?