20

The documentation says the following

Sets the HTTP protocol version for proxying. By default, version 1.0 is used. Version 1.1 is recommended for use with keepalive connections and NTLM authentication.

In my nginx config I have

    location / {
        proxy_http_version 1.1;
        proxy_pass http://127.0.0.1:1980;
    }

Doing http://127.0.0.1:1980 directly I can see my app get many request (when I refresh) on one connection. This is the response I send

HTTP/1.1 200 OK\nContent-Type:text/html\nContent-Length: 14\nConnection: keep-alive\n\nHello World!

However nginx makes one request and closes it. WTH? I can see nginx sends the "Connection: keep-alive" header. I can see it added the server and date header. I tried adding proxy_set_header Connection "keep-alive"; but that didn't help.

How do I get nginx to not close the connection every thread?

2 Answers2

31

In order Nginx to keep connection alive, the following configuration is required:

  • Configure appropriate headers (HTTP 1.1 and Connection header does not contain "Close" value, the actual value doesn't matter, Keep-alive or just an empty value)

  • Use upstream block with keepalive instruction, just proxy_pass url won't work

  • Origin server should have keep-alive enabled

So the following Nginx configuration makes keepalive working for you:

upstream keepalive-upstream {
  server 127.0.0.1:1980;
  keepalive 64;
}

server { 
  location / { 
    proxy_pass http://keepalive-upstream;
    proxy_set_header Connection "";
    proxy_http_version 1.1;
  } 
}

Make sure, your origin server doesn't finalise the connection, according to RFC-793 Section 3.5:

A TCP connection may terminate in two ways: (1) the normal TCP close sequence using a FIN handshake, and (2) an "abort" in which one or more RST segments are sent and the connection state is immediately discarded. If a TCP connection is closed by the remote site, the local application MUST be informed whether it closed normally or was aborted.

A bit more details can be found in the other answer on Stackoverflow.

Sergey Ponomarev
  • 2,947
  • 1
  • 33
  • 43
Anatoly
  • 15,298
  • 5
  • 53
  • 77
  • 4
    Is it possible to have upstream keepalive **without** an ```upstream``` block? I have a situation where we're dynamically assigning the proxy_pass value based upon a variable (e.g. ```proxy_pass https://$new_server:$new_port;```. – DropPhone Mar 10 '20 at 21:10
  • 3
    @DropPhone did you ever figure out an answer to your question? I am wondering the same? – TheJediCowboy Jul 01 '20 at 21:31
  • 1
    What does the `keepalive 64;` do? is 64 the time to keep the connection alive? – Libby Lebyane Nov 15 '20 at 19:04
  • 2
    @LibbyLebyane it's the "maximum number of idle keepalive connections to upstream servers", see http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive – Ian Routledge Nov 16 '20 at 09:18
  • 3
    Is `upstream { ... }` a syntactically valid directive? Must there not be a *name* between the word `upstream` and the opening bracket? – Armen Michaeli Aug 22 '21 at 13:26
  • Despite what the docs say, shouldn't that line actually be `proxy_set_header Connection "keep-alive"`? Though HTTP/1.1 says keep-alive is the default behavior, popular clients such as browsers or Postman will send the "Connection: keep-alive" header regardless. I believe this is to avoid cases where the server doesn't adhere to spec and sends back "Connection: close" unless it receives an explicit "Connection: keep-alive" from the client, so would it hurt to do so here? – user3781737 Jun 08 '22 at 17:49
9

keepalive should enable in upstream block, not direct proxy_pass http://ip:port.

For HTTP, the proxy_http_version directive should be set to “1.1” and the “Connection” header field should be cleared

like this:

upstream keepalive-upstream {
    server 127.0.0.1:1980;
    keepalive 23;
}

 location / {
    proxy_http_version 1.1;
    proxy_set_header Connection ""; 
    proxy_pass http://keepalive-upstream;
}
wonton
  • 7,568
  • 9
  • 56
  • 93
wow qing
  • 352
  • 4
  • 9
  • 2
    Bear in mind that an upstream server may also elect to close the connection. This can happen when a 50x error is encountered. A packet capture can show you if this is the case. – Patrick Scott Best May 20 '21 at 20:59
  • 1
    Can proxy_http_version 1.1; and proxy_set_header Connection ""; be put in the http block and then apply to all contained location blocks, or do they have to be in each individual location block. – SScotti May 29 '22 at 14:00