Aspnetcore: Performance issue in UseProxyToSpaDevelopmentServer

Created on 30 Dec 2019  路  18Comments  路  Source: dotnet/aspnetcore

UseProxyToSpaDevelopmentServer causing a lot of time to forward the request.

The raw webpack/ng serve server is pretty fast, should be processed within 100ms, but UseProxyToSpaDevelopmentServer API have to wait for 4 seconds to handle this request.

To Reproduce

Create a angular SPA project (based on .NET Core 3.1), modify the Startup.cs, change UseAngularCliServer to UseProxyToSpaDevelopmentServer and hit Ctrl+F5 to run directly(and run ng serve in front-end folder at same time).

Checkout the browser F12, should see this:
image

When using raw webpack/ng serve command without proxy(http://localhost:4200), performance is much better:
image

Further technical details

  • .NET Core 3.1/3.1.100
  • Visual Studio 2019(16.4.2)
affected-few area-mvc enhancement help wanted severity-minor

Most helpful comment

Localhost tries IPv6 first (::1) and takes seconds to time out before trying IPv4. I assume the server is only listening in IPv4?

All 18 comments

Looks like the issue is related to this one: https://github.com/aspnet/AspNetCore/issues/16797

Do you know if the linked issue resolves your problem?

@pranavkm I grab the latest code and does not seem help, it does not resolve my problem.

@javiercn this seems related to https://github.com/aspnet/AspNetCore/issues/18062.

This issue has two parts:

  • Proxy currently not using singleton HttpClient, so it not respect the ETag/If-None-Match header, and every request will need to wait webpack-dev-server for 4 seconds(that's why browser navigate is pretty fast)
  • So why webpack-dev-server need to wait for 4 seconds? I found that this simple code will need to wait 4 seconds:
const http = require('http');
const server = http.createServer((req, res) => {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('OK!');
    console.log('YEAH~');
})
server.listen(5000, 'localhost');

For reason unknown, just replace the localhost with 127.0.0.1, the 4 seconds waiting suddenly disappear, and I tried ASP.NET Core kestres server, using localhost is just fine/no waiting(I don't know why).

So, for reason unknown, I just need to replace the localhost with 127.0.0.1, I can gain a huge performance improvement, this is nothing related with .NET Core, seems a bug in node.js.

  • Proxy currently not using singleton HttpClient, so it not respect the ETag/If-None-Match header, and every request will need to wait webpack-dev-server for 4 seconds(that's why browser navigate is pretty fast)
    *

Do you mean the HttpClient used by the spa extensions? There is no singleton HttpClient AFAIK on the SPA extensions, I'm not sure if it uses its own HttpClient and keeps it around or if it creates a new one every time.

With regards to the ETag / If-None-Match i don't think HttpClient has logic to handle those things or that we implement our own. Best case scenario, the OS handles it for you, but I don't think that's the case.

For reason unknown, just replace the localhost with 127.0.0.1, the 4 seconds waiting suddenly disappear, and I tried ASP.NET Core kestres server, using localhost is just fine/no waiting(I don't know why).

So, for reason unknown, I just need to replace the localhost with 127.0.0.1, I can gain a huge performance improvement, this is nothing related with .NET Core, seems a bug in node.js.

Is this code on the template? I'm not sure why localhost might be different than 127.0.0.1 but maybe the OS/network stack takes some kind of shortcut. @Tratcher is this something you know about?

Localhost tries IPv6 first (::1) and takes seconds to time out before trying IPv4. I assume the server is only listening in IPv4?

@Tratcher Very likely. Do you see any downside to hardcoding 127.0.0.1 instead of localhost?

shrug it's better to fix the server if possible.

@Tratcher I don't think we can fix the underlying webpack/node server. I'm not sure this is an issue in the general case either.

Well, I know the 4 seconds issue is not related to .NET, but if you guys were node.js experts, you may take a look on this:
image

Note that the elapsed time is intervaled every 4 seconds(4, 8, 12, 16, ...), but when I change the code from localhost to 127.0.0.1 or IPv6 version "::1", performance is much better(no 4 seconds delay).

Well, I find the reason, it is really the ipv6 bug in node.js, by default, node.js will only listen to ipv4 loopback:
image

In the mean time, ASP.NET Core will respect both ipv4 and ipv6:
image

when HttpClient sending a request to localhost, HttpClient will first try the ipv6 version (for 4 seconds), and the fallback to ipv4 version of loopback address, that's why the asp.net core UseProxyToSpaDevelopmentServer(localhost:4200) will have to wait 4 seconds in every front-end request, and modify it to 127.0.0.1:4200, performance is all good.

But UseProxyToSpaDevelopmentServer([::1]:4200) works?

@Tratcher nop, as I said, node.js will treat localhost as ipv4 loopback address only, so by default ipv6 address is not working.

@Tratcher @javiercn
I believe Angular/React/Vue SPA extensions should using 127.0.0.1 instead of localhost here:
https://github.com/dotnet/aspnetcore/blob/968e85a3977d3634602891eecd90e456131ae0c3/src/Middleware/SpaServices.Extensions/src/AngularCli/AngularCliMiddleware.cs#L46-L52

If @Tratcher is happy with the solution to change it to 127.0.0.1, I believe we would be happy to take a PR for this change.

That's fine.

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

farhadibehnam picture farhadibehnam  路  3Comments

UweKeim picture UweKeim  路  3Comments

guardrex picture guardrex  路  3Comments

FourLeafClover picture FourLeafClover  路  3Comments

ipinak picture ipinak  路  3Comments