-
Notifications
You must be signed in to change notification settings - Fork 293
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Connection string property "Connection Timeout" is not respected. #2430
Comments
@dmytro-gokun which exact versions of EF Core and SqlClient and SqlClient are you using? It seems like SqlClient 5.1.2 - which EF Core 8.0.2 took a dependency on - introduced new behavior which triggers this (see dotnet/efcore#33399 for more details). |
@roji We are not really using EF Core. Microsoft.Data.SqlClient version 5.2.0 is referenced in this test project
I'm not sure what this number means :). Could you give me a link? |
@dmytro-gokun apologies, I mistakenly thought this issue was on the EF repo. To help narrow down the issue, can you please try downgrading to Microsoft.Data.SqlClient v5.1.1, and see if you're still seeing the slowness? |
@roji Yes, I do. I've tried 5.1.1, 4.0.5, 3.1.5, 2.1.7. All show the same behavior. In fact, I was able to "fix" by introducing timeout in the calling code:
This does not look like a good solution though, just a temporary one until SqlConnection is fixed |
OK, I'll let the SqlClient folks take it from here... |
It all pretty much comes down to the fact that SqlClient opens physical connections one at a time (and in a separate thread). SqlClient/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs Lines 1150 to 1156 in 30cd171
That thread synchronously goes through every single open request and tries to open a physical connection: SqlClient/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs Lines 1046 to 1072 in 30cd171
The way opening a physical connection works is that there are multiple handles (one for getting a connection from a pool, one to open a physical connection, one for errors), so SqlClient just waits for any of them to fire: SqlClient/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs Lines 1189 to 1216 in 30cd171
At this point timeout (
|
@vonzshik Great insights, thank you! Clearly looks like a bug to me. |
Every time I say that something looks like a bug I'm usually replied with "it's by design" 😢 private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObjectsTimeout, bool allowCreate, bool onlyOneCheckConnection, DbConnectionOptions userOptions, out DbConnectionInternal connection)
{
if (waitForMultipleObjectsTimeout == 0)
{
connection = null;
return false;
}
/// other stuff unchanged It's not going to help completely since eventually that thread is going to start getting requests with a near-zero timeout (or more like it's going to fluctuate, as in on the first request it tries to open a physical connection, then skips a few requests because their timeout is going to be 0, then get another with a near-zero timeout and tries to open, then again skips a few, etc), but all in all should be a bit better behavior. |
@vonzshik Well, it could not be by design that a connection attempt stalls for minutes killing an entire multi-threaded app where it is supposed to fail safely in few seconds .. |
Have you tried setting ConnectRetryCount=0 to disable transient fault handling? |
@cheenamalhotra Yes, does not help. Neither does disabling pooling altogether |
@cheenamalhotra Any update here? |
I think you're experiencing a combination of known issues:
To achieve true parallelism with fail fast support, you'd need to:
We are going to bring this support in |
@cheenamalhotra That's something. Actually, i've found that just replacing OpenAsync() with Open() w/o OpenWithoutRetry does the trick. Is not that strange?
Will that require disabling pooling as well? Honestly, i do not like doing that in the high-load environment |
The pooling issue requires connection pool changes and is not covered with the changes made in the PR #2433 as of now. It will enable failing fast, but if setting |
Since this is a duplicate of #601 and depends on it, I'll proceed to close this one. |
Setting aside retries, the fact that SqlClient opens physical connections from a ctor (which makes true async impossible) and whatnot. Whenever |
We have a high-load service which we want to run robustly when SQL server becomes (temporarily) unavailable. To achieve this, we set Connection Timeout (and Command Timeout as well, but that is not important for the purpose of this issue). We then expect connection attempt fail fast if the SQL server is not available. This way, our server will be able to do its job even if the SQL server is down for some time. But, somehow this does not work as expected. Following code emulates our multithreaded server attempting to connect to an (unavailable) SQL server from multiple threads a time:
When this code is run outputs something like:
So, clearly Connection Timeout is not being respected. This causes our server to stall completely when SQL server is down. This is not the way we want it to work :). Any idea why we are observing this behavior?
The text was updated successfully, but these errors were encountered: