views:

233

answers:

2

All the examples I've seen of sock.listen(5) in the python documentation suggest I should set the max backlog number to be 5. This is causing a problem for my app since I'm expecting some very high volume (many concurrent connections). I set it to 200 and haven't seen any problems on my system, but was wondering how high I can set it before it causes problems..

Anyone know?

Edit: Here's my accept() loop.

while True:    
    try:
        self.q.put(sock.accept())
    except KeyboardInterrupt:
        break
    except Exception, e:
        self.log("ERR %s" % e)
+3  A: 

The doc say this

socket.listen(backlog) Listen for connections made to the socket. The backlog argument specifies the maximum number of queued connections and should be at least 1; the maximum value is system-dependent (usually 5).

Obviously the system value is more than 5 on your system. I don't see why setting it to a larger number would be a problem. Perhaps some memory is reserved for each queued connection.

My linux man page has this to say

If the backlog argument is greater than the value in /proc/sys/net/core/somaxconn, then it is silently truncated to that value; the default value in this file is 128. In kernels before 2.4.25, this limit was a hard coded value, SOMAXCONN, with the value 128.

gnibbler
Just checked on osx, `socket.SOMAXCONN` is 128 too.. Kinda sucks, means the max number of current pending connections is 128.. Sure, that's a lot, but given the short/fast nature of these requests.. I was hoping for more concurrency.
Ian
No, the kernel will just fail to ACK connection requests after SOMAXCONN. This is desired behavior; if you are really holding more than 128 queued connect requests you are a) taking too long to process them or b) need a heavy-weight distributed server or c) suffering a DDoS attack.
msw
@Ian, on linux you can `echo 256 > /proc/sys/net/core/somaxconn`. However you should strive to make your handler faster before you increase this number regardless
gnibbler
Hmmm, alright, I guess 128 should be the max, mind you, I'm not sure how I can make the `sock.accept()` loop go any faster.. What if I made a few threads to accept incoming connections?
Ian
+1  A: 

You don't need to adjust the parameter to listen() to a larger number than 5.

The parameter controls how many non-accept()-ed connections are allowed to be outstanding. The listen() parameter has no bearing on the number of concurrently connected sockets, only on the number of concurrent connections which have not been accept()-ed by the process.

If adjusting the parameter to listen() has an impact on your code, that is a symptom that too much delay occurs between each call to accept(). You would then want to change your accept() loop such that it has less overhead.

In your case, I am guessing that self.q is a python queue, in which case you may want to call self.q.put_nowait() to avoid any possibility of blocking the accept() loop at this call.

Heath Hunnicutt
If that's true then there's something wrong with `ab`, because increasing the size of `backlog` fixed my problems.
Ian
@Heath, it's possible if there are a lot of connections being made every second. A large backlog will allow you to tandle transient load better
gnibbler
@Ian: What is "ab"? As I wrote in my answer, if increasing the backlog fixes your problem, that means you aren't calling accept() frequently enough to keep up with incoming connections. How does your accept() code work?
Heath Hunnicutt
@gnibbler, any transient spike will be handled by client retries. Any chronic overload will be handled by timeouts on connection, as TCP was designed. Using SOMAXCONN might be advisable, but running into this problem is a sign that there is a defect elsewhere in the server implementation, and that shouldn't be glossed over to the OP's disadvantage.
Heath Hunnicutt
@Heath, 5 seems kind of low. Maybe it is a relic from the Win98 days. The default in linux is 128 nowdays. I wonder if there is a way to monitor the highwater mark for the backlog on a busy server.
gnibbler
@Heath, I edited my original post to show the process. As for `ab`, it's a linux command (apache bencmark), it basically hammers a server with x requests at y concurrency. Eg. `ab -n 1000000 -c 128 192.168.1.185:10001/` makes a million requests at a concurrency of 128 connections. It seems if I set the concurrency above the SOMAXCONN, the app starts dropping connections.
Ian
Heath Hunnicutt