Skip to content
This repository has been archived by the owner on Apr 8, 2020. It is now read-only.

Delay in server-side rendering after a few minutes of idling #1368

Closed
magnus-tretton37-zz opened this issue Nov 1, 2017 · 6 comments
Closed

Comments

@magnus-tretton37-zz
Copy link

I've applied SSR to a React/Redux app pretty much exactly like the docs here describe (in combination with the example template for the react+redux SPA template). Everything works, but if I let the app idle for just a few minutes, the page load suddenly takes a second extra (this is running just the asp.net core process, outside IIS, and it's not the very first startup-load, that understandably takes slightly longer). The same thing happens when I build and run the VS template (hello world w weather forecast), so it doesn't seem to be just my own app.

It might not sound like a lot, but it's frustrating when a reload (without cache) takes 2-300 ms and a"fresh" page load takes 1.2-1.3 s. You say here #589 that there is no shutdown of anything node-related once it's all started, but the difference in loading time between consecutive page loads or with a few minutes in between is noticeable (and measurable in chrome devtools). So what could be behind this behavior? And is it avoidable?

I'm using node 8.9.0, dotnet core 2.0, the latest npm and nuget packages where applicable. Thanks for the help.

@SteveSandersonMS
Copy link
Member

I wouldn't expect this to be related to SSR. It's possible that either Node or ASP.NET or IIS or any combination of these choose to discard cached data or recycle after they have been left alone for a while. For example, here's someone reporting this about IIS: https://stackoverflow.com/questions/40467009/net-core-slow-after-idle

You could use the 'heartbeat' (intermittently make a request to your own server) workaround if this is a problem in your scenario.

However, if you do have reason to believe it's something specific in the code in this repo or the template, please let us know the details!

@magnus-tretton37-zz
Copy link
Author

magnus-tretton37-zz commented Nov 29, 2017

I recently saw this #1392 and decided to investigate some more. What I found:

  • The first time Node is called takes ca 2 s, then it goes down to 10-50 ms (time is in NodeServices, not page load).
  • After ca 40 seconds of idling, the Node invocation takes ca 1 s longer. The extra time can be traced to the actual call into Node, i.e. InvokeExportAsync in HttpNodeInstance.cs (the _client.PostAsync - line)
  • Thinking this could be related to Http, I tried using the Socket hosting model instead. Doing so reduced the initial invoke time from 2 s to 1 s and eliminates the extra second after idling. So maybe there's something going on with the Node Http hosting model? Maybe that's outside the scope of this project, but I assume more and more people will notice this issue, so the more info the better.

I should add that the testing was done with the github code, so version 2.1.

After testing, I tried switching to Socket hosting for real using the (beta) package on Nuget, but that doesn't seem to work. I get the error:

Method not found: 'Void Microsoft.AspNetCore.NodeServices.HostingModels.OutOfProcessNodeInstance..ctor(System.String, System.String, System.String[], System.String, Microsoft.Extensions.Logging.ILogger, System.Collections.Generic.IDictionary`2<System.String,System.String>, Int32, Boolean, Int32)

@AlrikOlson
Copy link

AlrikOlson commented Jan 11, 2018

I'm working with a Vue.js SSR template and I'm focusing on getting performance to be consistently good on a basic component rendered server-side. The main issue I'm having is a ~1s delay on the SSR endpoints if I wait more than a couple seconds to do a hard refresh of the page. If I spam refresh, the server-side rendering seems to be as fast as expected.

However, upon waiting a few seconds longer than normal there is an extra 1000ms of delay added to the TTFB of the response. The very next refresh is usually instant.

When looking at Application Insights in Visual Studio, you can clearly see that the HTTP request .Net Core makes to the node instance is taking that extra 1000ms of time. One other note is that this behavior occurs both when running on Kestrel by itself, IIS Express, and as a site on a production IIS instance.

The VueJS component is extremely basic and does not make any internal or external data requests.

One other note: This behavior never occurs on plain MVC views without any SPA pre-rendering added to them.

@aloker
Copy link

aloker commented Feb 18, 2018

I can confirm the exact same issue. After a couple of seconds of idling, requests using SSR take exactly one second longer. OTOH, spamming the site yields very low latency. The extra delay is pretty much the same on my dev machine and the server the app is deployed to. I added a stopwatch around the call to ISpaPrerenderer.RenderToString. It's exactly that call that takes one second longer. Release vs Debug builds make no difference.

Tested with Node 8.9.4 and Node 9.5.0
DotNetCore Windows Hosting 2.0.5

@aloker
Copy link

aloker commented Feb 18, 2018

OK, I did more research. I think this is related to the keepAliveTimeout of the node http server that handles the requests. As of Node 8, the server will close its socket after 5 seconds of inactivity.

https://nodejs.org/api/http.html#http_server_keepalivetimeout

This coincides with the effect that I'm seeing - after 5 seconds of idling the next request takes longer. The pre-Node 8 behavior is to keep the socket alive. When I downgrade to Node 6.13.0, the one second delay only occurs after a couple of minutes of idling, not as before after 5 seconds. It still occurs, but I'm still investigating how to fix this.

Edit: I created a new ticket for this: #1542

@pats
Copy link

pats commented Mar 7, 2018

@aloker good investigation, I confirm your solution, downgrade to Node 6.13.0 seems to solve issue

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants