I'm writing an application on x86_64 CentOS 7 that functions as a server, managing potentially thousands of devices. Because my application doesn't do so well when running through the connection process (various application-layer handshaking, DB operations, etc.) and it's conceivable that thousands of devices could come online simultaneously, I want to try rate-limiting connection accepts (as a possible "cure at source" approach to my scale problems).
In brief, incoming connections would be "rejected" in some fashion while the application-handshaking process for n devices is already underway (be this an n per T time limit, or a n concurrent handshakes limit).
- simply dropping connections on
accept()will not invoke the reconnection backoff mechanism on the devices, so re-attempts would be noisy
- we can't temporarily "unlisten" on a socket (plus I'm not wild about clients having to deal with timeouts, rather than simply getting "connection refused")
- we also can't change the
listenbacklog size at runtime
- and I don't want to leave incoming connections in the backlog, pending an artificially delayed
accept(), because my epoll is level-triggered and it would cause a bit of an architectural nightmare to work around the resulting "tight loop"
I hear that the overhead of
accept() is not high (particularly when compared against actual I/O), so I'm inclined to simply shut down my listen socket when I'm already handling (say) 100 reconnections, then re-open/re-
listen() it when the coast is clear.
But this somehow feels like the wrong way to go about matters.
How would you approach this problem, given the above constraints?