16

I've noticed that after a period of time my ASP.NET Core Web API services seem to go through the same initialisation process you get when you launch them fresh, i.e. the initial request is slow, but subsequent requests are fast.

Is there a common technique for keeping controllers warm so this doesn't happen? For reference I'm not using IIS (as far as I'm aware), these services run in Docker using Microsoft's official .NET Core docker images (not Alpine based).

I should also point out that controllers within these services are pre-warmed on launch via a /ready endpoint that's invoked by Kubernetes as a readiness check. The issue is that this doesn't seem to stick particularly long.

Zoe
  • 27,060
  • 21
  • 118
  • 148
  • How slow is slow? How fast is fast? How long do you need to wait until fast becomes slow? Are you seeing it on a single client or across multiple? Might it be DNS related? – mjwills Jun 20 '18 at 09:10
  • im not sure with microsoft docker, but if you use IIS, you could refer to this link https://stackoverflow.com/questions/21150237/asp-net-mvc-slow-initial-load. maybe you could find some similar settings in your application – Mark Jun 20 '18 at 09:17
  • 1
    It would be awesome if you could provide a [mcve] so we can see the controller in question, and its dependencies. – mjwills Jun 20 '18 at 09:24
  • @mjwills slow -> 8 seconds, fast -> 300ms. Multiple clients, and the services are scaled out to 3 instances across 3 nodes in my cluster, so it's not a question of load masking the issue. –  Jun 20 '18 at 10:41
  • 2
    @mjwills not yet, however I double checked the Npgsql documentation and noticed it will close idle connections after 5 minutes by default so I reckon this is likely the root cause. Need to profile to confirm. –  Jun 20 '18 at 11:09
  • That is why the [mcve] is crucial - it provides us valuable context. – mjwills Jun 20 '18 at 11:10
  • @lyptt Have you considered using livenessProbe? It may help to keep your controllers warm...? – Kiryl Jul 02 '18 at 18:06
  • 1
    Isn't this simply because of the native C# JIT compiler? – Dandy Mar 23 '19 at 02:35
  • You may also look for thread starvation kind of issues in this case. If threadpool for some reason keeps the minimal count of threads low, the app won't respond to a large number of requests effectively. You can experiment with SetMinThreads() to determine the issue, but be careful using it in production. https://learn.microsoft.com/en-Us/dotnet/api/system.threading.threadpool.setminthreads?view=netframework-4.8 – Sergey Nikitin Nov 15 '19 at 08:36
  • are you using a memory cache or create a db connection with this /ready call? perhaps the memory is flushed out or the connection has a max idle time. sometimes these are the cases. – Ori Refael Nov 30 '19 at 23:17

2 Answers2

1

This definitely doesn't sound like a controller issue. Controllers are typically a new instance for every request. When you mentioned "slow -> 8 seconds, fast -> 300ms" in a comment, this is definitely not Kestrel or controller related.

Your issue could be any number of things, but here's a couple guesses:

  • If you are running your app in Windows (like an Azure App Service), then it is running under IIS. You may need to check your IIS and hosting settings. Some hosts will pause your web service if it's a "cheap" tier.

  • "slow -> 8 seconds" this honestly sounds like your have an external call that is slow. Perhaps a Db, external API, or something re-authenticating.

ermish
  • 1,160
  • 2
  • 13
  • 26
0

If this experience of yours is in your development box/personal machine, and when you experirence this during everytime you begin debug or run your app, it may. But in real time, it certainly not going to be the case (except for the very first run or after the app pool is being recycled or the service instance is restarted). Even then, in the server, that difference should be very minimal. With .net core, it should be even minimal delay experience.

Ak777
  • 346
  • 7
  • 18