9
votes

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).

1

1 Answers

5
votes

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.