Closed vbanos closed 6 years ago
Incoming queues that cannot be accepted wait in the accept queue. If we accept incoming connections ASAP, connection timeout will not happen but maybe read timeout will happen later.
In addition, in order to avoid dropping connections in the accept queue, we tune sysctl variables net.core.somaxconn=4096
and net.ipv4.tcp_max_syn_backlog=4096
Currently, when the number of active requests is greater than
max_threads
, we dotime.sleep(0.05)
and check again indefinitely until we can accept the request. Also, when this happens, theunaccepted_requests
counter is incremented.This condition creates an issue. The number of incoming requests must be no more that the number of warcprox threads(!) and limits the capacity of warcprox to handle incoming requests. If we select to use a small number of
max_threads
and we have a fair number of browsers using warcprox, a lot of requests will wait.Since the
ThreadPoolExecutor
we use has a queue, we can accept all requests regardless of the number ofmax_threads
and we'll serve them when we can (The queue is FIFO). The clients will have their connections accepted and maybe wait a bit for response but they won't be blocked.Also, VERY important is that we'll be able to keep the number of
max_threads
low. In my performance tests using a VM with 4 CPU cores, I setmax_threads=20
and I sawactive_requests
reach values ~50 withoutseconds_behind
increasing over 1 sec.In addition, another improvement in this PR is that we convert
PooledMixIn.active_requests
to a simple counter instead of a set(). We use this var only to add/remove requests and dolen(self.active_requests)
to report their numbers. Since we don't do anything with the set contents, there is no point to keep it in memory. We'll just do self.active_requests +-1 when necessary.TODO: If this PR is OK up to this point, I also need to remove
unaccepted_requests
from everywhere.