Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Server-Sent Events connection timeout on Node.js via Nginx

I have a Node.js via Nginx setup and it involves Server-Sent Events.

No matter what Nginx configuration I have, connection of sse is broken after 60 seconds and reinitialized again. It doesn't happen if I connect to application directly on port on which node serves it, so it's clearly some Nginx proxy issue.

I'd like to have no timeout on sse connection. Is that possible? I've tried tweaking send_timeout, keepalive_timeout, client_body_timeout and client_header_timeout but it doesn't change anything. Below is my Nginx configuration.

upstream foobar.org {
   server 127.0.0.1:3201;
}

server {
  listen 0.0.0.0:80;
  server_name   example.org;

  client_max_body_size 0;
  send_timeout 600s;

  location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-NginX-Proxy true;

    proxy_pass http://example.org/;
    proxy_redirect off;

    proxy_set_header Connection '';
    proxy_http_version 1.1;
    chunked_transfer_encoding off;
    proxy_buffering off;
    proxy_cache off;
  }
}
like image 703
Mariusz Nowak Avatar asked Feb 07 '14 14:02

Mariusz Nowak


1 Answers

Answering to myself. Actually solution was not that difficult to find, it just demanded careful look into nginx documentation.

proxy_read_timeout is a directive responsible for that, and by default it's set to 60 seconds. So it can be easily fixed by setting e.g.:

proxy_read_timeout 24h;

Setting 0 won't work, it will actually make all your connections broken, therefore we need to come up with long enough timeout.

After fixing that I approached also the other issue, but this time related to how browsers handle the connection. For some reason after 5 minutes of inactivity browsers silently discard the connection. What's worse neither side is informed that it's discarded, for both it still appears as if connection is online, but data doesn't get through. Fix for that is to send some keep alive ping on interval basis (plain sse comment works great).

like image 171
Mariusz Nowak Avatar answered Oct 14 '22 16:10

Mariusz Nowak