dotnet / AspNetCore.Docs

Documentation for ASP.NET Core
https://docs.microsoft.com/aspnet/core
Creative Commons Attribution 4.0 International
12.64k stars 25.29k forks source link

Document reverse proxy usage with SignalR #10827

Open BrennanConroy opened 5 years ago

BrennanConroy commented 5 years ago

We should write a doc that has example reverse proxy configurations and common pitfalls that can occur.

One example is that SSE with nginx likely wont work by default because the request is buffered. Nginx configuration can turn buffering off via proxy_buffering off; but you might only want to turn it off for SignalR specific requests via:

server {
    location /hubroute {
        proxy_buffering off;
    }
}

Another way to fix that issue is to send X-Accel-Buffering: no with your Http requests, so we could mention how to do that also.

WebSockets is another option that can sometimes need configuration in your proxies. proxy_set_header Connection $http_connection;

bradygaster commented 5 years ago

I like the idea. You feel it should go into the "hosting and scaling" or "server concepts" TOC item? I think the former makes sense if we make a new article.

Or, is it small enough that it'd make for a good section in an existing article?

BrennanConroy commented 5 years ago

Hosting and scaling sounds right, however, if when we write it it gets too large, we can make a new article.

davidfowl commented 4 years ago

Pretty sure there are more issues, like configuration for sticky-sessions as well

BrennanConroy commented 4 years ago

Info dump

http {
  map $http_upgrade $connection_upgrade {
    default Upgrade;
    '' close;
  }

  server {
    server_name some_name;
    listen 80 default_server;

    root /path/to/wwwroot;

    # Configure the SignalR Endpoint
    location /hubroute {
      proxy_pass http://localhost:5000;

      # Configure WebSockets
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
      proxy_cache_bypass $http_upgrade;

      # Configure ServerSentEvents
      proxy_buffering off;

      # Configure LongPolling
      proxy_read_timeout 100s;

      proxy_set_header Host $host;
    }
  }
}

If you have multiple servers configured you will need to enable sticky sessions so clients wont get random 404's by hitting a different backend:

http {
  upstream backend {
    server http://localhost:5000;
    server http://localhost:5002;

    # for Nginx Plus
    sticky cookie srv_id expires=max domain=.example.com path=/ httponly;

    # for Nginx Open Source
    ip_hash;
  }
}

And change the server block from proxy_pass http://localhost:5000 to proxy_pass http://backend

halter73 commented 4 years ago
 map $http_upgrade $connection_upgrade {
   default Upgrade;
   '' close;
 }
proxy_set_header Connection $connection_upgrade;

Does this mean that every request to /hubroute will always contain either a "Connection: upgrade" or a "Connection: close" header? We wouldn't want to disable keep-alive for long polling.

halter73 commented 4 years ago

It looks like #12774 is tracking this for Apache. @AlbertoPa provided what appears to be a working config in the issue, but we'll need to test this out.

guardrex commented 4 years ago

I closed #11403 as a dup. Just one quick reminder note to cross-link the coverage in the Linux Nginx topic.

BrennanConroy commented 4 years ago

Does this mean that every request to /hubroute will always contain either a "Connection: upgrade" or a "Connection: close" header? We wouldn't want to disable keep-alive for long polling.

"Connection: close" is applied by default with nginx. "Connection" is a hop-by-hop header and isn't supposed to be forwarded by proxies.