Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test nginx proxy timeouts

Target:

I would like to test all Nginx proxy timeout parameters in very simple scenario. My first approach was to create really simple HTTP server and put some timeouts:

  1. Between listen and accept to test proxy_connect_timeout
  2. Between accept and read to test proxy_send_timeout
  3. Between read and send to test proxy_read_timeout

Test:

1) Server code (python):

import socket
import os
import time
import threading

def http_resp(conn):
    conn.send("HTTP/1.1 200 OK\r\n")
    conn.send("Content-Length: 0\r\n")
    conn.send("Content-Type: text/xml\r\n\r\n\r\n")

def do(conn, addr):
    print 'Connected by', addr
    print 'Sleeping before reading data...'
    time.sleep(0) # Set to test proxy_send_timeout
    data = conn.recv(1024)
    print 'Sleeping before sending data...'
    time.sleep(0) # Set to test proxy_read_timeout
    http_resp(conn)
    print 'End of data stream, closing connection'
    conn.close()

def main():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(('', int(os.environ['PORT'])))
    s.listen(1)
    print 'Sleeping before accept...'
    time.sleep(130) # Set to test proxy_connect_timeout
    while 1:
        conn, addr = s.accept()
        t = threading.Thread(target=do, args=(conn, addr))
        t.start()

if __name__ == "__main__":
    main()

2) Nginx configuration:

I have extended Nginx default configuration by setting explicitly proxy_connect_timeout and adding proxy_pass pointing to my local HTTP server:

    location / {
        proxy_pass http://localhost:8888;
        proxy_connect_timeout 200;
    }

3) Observation:

proxy_connect_timeout - Even though setting it to 200s and sleeping only 130s between listen and accept Nginx returns 504 after ~60s which might be because of the default proxy_read_timeout value. I do not understand how proxy_read_timeout could affect connection at so early stage (before accept). I would expect 200 here. Please explain!

proxy_send_timeout - I am not sure if my approach to test proxy_send_timeout is correct - i think i still do not understand this parameter correctly. After all, delay between accept and read does not force proxy_send_timeout.

proxy_read_timeout - it seems to be pretty straightforward. Setting delay between read and write does the job.

So I guess my assumptions are wrong and probably I do not understand proxy_connect and proxy_send timeouts properly. Can some explain them to me using above test if possible (or modifying if required).

like image 687
mkorszun Avatar asked Jun 24 '13 15:06

mkorszun


People also ask

What is nginx proxy connection timeout?

proxy-connect-timeout : this defines the timeout for establishing a connection with a proxied server. The default value is 60 seconds, and the timeout typically cannot exceed 75 seconds.

Where is Nginx timeout set?

For example, you want to increase request timeout to 300 seconds. Then you need to add proxy_read_timeout, proxy_connect_timeout, proxy_send_timeout directives to http or server block. Here the http block allows the changes in all server in NGINX.

What is proxy_read_timeout?

This is easy to understand -- Nginx is about to connect to an upstream "backend" server and if it can't connect within an X amount of time it will give up and return an error. The server is unreachable, has too many connections, etc. proxy_read_timeout Defines a timeout for reading a response from the proxied server.


1 Answers

According to the docs the connect timeout cannot be more than 75 seconds, which may explain why it's timing out sooner than you expected. Not positive, however. I've never really done work with the low-level python sockets library so it may be accepting the connection into the pool at a low level before you actually call s.accept() in your program.

Send timeout works by measuring time between two chunks of data heading towards the upstream server. Since you're sending the entire response in one chunk I'm guessing in your implementation you're hitting the read timeout again, rather than a send timeout. If you send one chunk, then wait past the send timeout to send the rest of the response and close the connection, you should hit the send timeout.

like image 154
Michael Pratt Avatar answered Oct 02 '22 21:10

Michael Pratt