-
Notifications
You must be signed in to change notification settings - Fork 191
Description
Hi. We were faced with the fact that we began to constantly receive exceptions in various of our services associated with a timeout when establishing a connection:
Oracle.ManagedDataAccess.Client.OracleException (0x80004005): Connection request timed out
at OracleInternal.ConnectionPool.PoolManager`3.Get(ConnectionString csWithDiffOrNewPwd, Boolean bGetForApp, OracleConnection connRefForCriteria, String affinityInstanceName, Boolean bForceMatch)
at OracleInternal.ConnectionPool.OraclePoolManager.Get(ConnectionString csWithNewPassword, Boolean bGetForApp, OracleConnection connRefForCriteria, String affinityInstanceName, Boolean bForceMatch)
at OracleInternal.ConnectionPool.OracleConnectionDispenser`3.Get(ConnectionString cs, PM conPM, ConnectionString pmCS, SecureString securedPassword, SecureString securedProxyPassword, OracleConnection connRefForCriteria)
at Oracle.ManagedDataAccess.Client.OracleConnection.Open()
at System.Data.Common.DbConnection.OpenAsync(CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsync(Boolean errorsExpected, CancellationToken cancellationToken)
Oracle.EntityFrameworkCore 3.19.80
Oracle.ManagedDataAccess.Core 2.19.80/100
Errors occur both on test environments and in production. At first I suspected that our services were exhausting all available connections in the connection pool (we use pooling as it is enabled by default). I thought about this after reading the documentation. So I wanted to test the hypothesis using performance counters (see #123) but counters work only on Windows and our backend runs in Kubernetes. So I started looking for other ways. I knew about the possibilities to enable tracing. At the same time, I did not want to load our services with tracing. In addition, the trace is not very convenient to write to a file. So I wanted to manually access the inner classes and read the state of the connection pool. Fortunately, I noticed the OracleConnection.Dump()
method, which is also used by the tracing itself. I examined the source code for this method and realized that it outputs the status of the pool - the total number of connections in the pool and the number of free connections. This information was perfect for me for analysis. I started calling this method in EF Core interceptor every time a connection level error occurred (Microsoft.EntityFrameworkCore.Diagnostics.ConnectionErrorEventData). The results surprised me. It turns out that the error in most cases occurs when the pool is empty. Output from OracleConnection.Dump()
:
(DUMP)
What can you advise in such a situation? Also I saw this article.
I want to note that we get errors even during the initial warm up of the services, when we make a call to our databases in advance.