-
Notifications
You must be signed in to change notification settings - Fork 4k
Why does the IdentityServer4.EntityFramework project not use asynchronous EF methods? #2067
Comments
UPD: Is there any reasons why it does not merge into the main branch? |
We've had issues with the underlying EF implementation under load. |
Currently we can see the following behavior - under load and with a long ping to DB, all application's threads get busy. Kestrel successfully processes connections, but the application is not responsible for sufficient time. Our application is IdentityServer4 + IdentityServer4.EntityFramework on Kestrel. Nothing more |
What kind of issues did you have? Do you have any load tests? |
@brockallen I have another question - why don't you use AsNoTracking for read-only queries? Is there any reason for this? Can I put them on? |
@brockallen I added AsNoTracking for readonly queries - IdentityServer/IdentityServer4.EntityFramework#136 |
What does |
Is this designed to hold the value of DNT - or DoNotTrack from the HTTP header? DNT would mean (inter alia) that any existing OP signin cannot store or release information about the sites visited. (Obviously the OP does record all the clients that have been registered for a user, at least if pairwise sub is implemented.) It should imply that no client or external provider can get any information about signin to other sites. Vanilla OpenID Connect should provide this by default. API grants might leak this information if not careful. |
@brockallen AsNoTracking avoids the overhead of setting up change tracking for each entity instance. See https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.entityframeworkqueryableextensions.asnotracking?view=efcore-2.0
|
Since this store API is designed as read-only, would it make more sense to set this globally? https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.changetracking.changetracker.querytrackingbehavior?view=efcore-2.0#Microsoft_EntityFrameworkCore_ChangeTracking_ChangeTracker_QueryTrackingBehavior? |
On a per project basis, yes. It would be a breaking change to bring into the EF library though. A lot of people are using the context's and our registrations for client & scope management. |
Actually, yea, so maybe it's the extension method level where we could do this rather then in the DbCOntext defaults. |
Also, does anyone really know the perf difference for using this? |
@brockallen I have prepared some simple benchmarks Here is the results:
|
What do you think about it? |
I've not had time to consider it. In general I think I will like the idea -- I just need to spend the time learning more about it. |
As you should have seen from the other issue, the AsNoTracking was merged. Thanks! We're still debating the async EF features. Feel free to comment on that. |
No additional input on this thread? We're planning on releasing a 2.3 preview1 soon, so time to discuss is now. |
It is suprising to me that EF access is sync. Everywhere in Asp.Net Identity it is async. So I think IdentityServer should follow this pattern. |
@D3MaxT From what I've seen, using async when hitting the DB puts more stress on the DB. Or you end up allow more throughput into your web server, which causes more connections to be requested, which then floods the connection pool, and you get time out exceptions. So by blocking synchronously you're sort of throttling the attempts to the DB, thus distributing the load. Too many async operations to the DB concentrates the load. I admit, I'm not an expert in this area. This is just what I've seen. |
Late to the party, but I think this makes sense to do. I have been trying out https://github.com/benaadams/Ben.BlockingDetector , which clearly tells you that this is a bad idea, and I'm pretty sure Ben Adams is an expert :) Is there anything I can do to convince you/progress on the issue? |
@brockallen your observation isn't wrong. It's mostly because once you lifted the bottleneck on the web server, the DB become the next target. But it doesn't mean that the bottleneck on the web server should stay in place. As @jepperc mentionned, blocking threads in async code isn't a good the way to avoid hitting a bottleneck on the DB server. The current implementation can also impact requests on the same thread that would otherwise not be blocked. |
What about using Entity Framework DbContext Pooling ? Good blog that explains connection pooling Benefit
Drawback
This should keep any bottlenecks in the code and not push them to the database. |
My take on it is that we shouldn't be intentionally throttling in the application by using synchronous IO when there's an async alternative. It's about efficient use of threads rather than absolute response times. If rate limiting is the goal then this should be managed at traffic manager level IMO - it can make much better decisions about how to go about doing that. It does have implications though. We've encountered connection pool exhaustion under load testing before. The lack of blocking and the huge and sudden ramp up of the load test caught the application off guard and it just couldn't open connections fast enough. The data access in IDS4 is nearly all simple queries producing small result sets and single row updates/inserts using clustered indexes so we've never even got close to a performance problem even on quite a modest DB server setup with synchronous commits to the secondary in an AlwaysOn cluster. This is despite scaling out (and thus supporting more throughput even for synchronous operations) the application multiple times over the last couple of years. I'm willing to create my own async versions and be a bit of a guinea pig - I've got no qualms about the stability of async EF in a production environment. |
This is slated for our 4.0 release, which will target ASP.NET Core 3.1 (which will be their LTS). |
Good to know, thanks. We're currently completing our 1.1 -> 2.1 upgrade - painful. I'm thinking 2.1 -> 3.1 LTS will be a lot easier when it's available. |
is it ok to work on this and open a PR ? or you have other plans ? |
I was quite surprised to see that IdS4 is having the same (?) issue with Thread Pool starvation we have with IdentityServer3 (according to the reports above). V3 is using async EF methods by default, but there is a caveat -- the class (also wondering how synchronous methods are implemented by the EF -- if they are the wrappers against the asynchronous (like the trick with |
I know it's not ideal to use external libraries but I believe Polly is included by default in the ASP.NET Core metapackage now. Have you considered leveraging Polly's Bulkhead-Isolation, Rety (with exponential back up), and Circuit Breaker policies to prevent load from causing starvation or affecting other processes? |
finally done in PR. |
* update test db names for 3.1 * use asynchronous EF methods #2067 * update tests and json to be 3.1 DB connection string * add async to cors service * remove sql server from tests to try to fix build deadlock * Revert "remove sql server from tests to try to fix build deadlock" This reverts commit 612b254. * remove appveyor task * add command to start localdb * convert to cmd task * change void test to async * revert start localdb
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Hi, I'm surprised that all calls to Db Context are synchronous. And I'm ready to replace them with asynchronous ones.
I wanted to know why it was not done before?
Is there any good reason for this?
The text was updated successfully, but these errors were encountered: