Refactor `ratelimit.acquire()` to properly enforce the *globalMaxConn*
limit.
This commit is contained in:
Aditya Manthramurthy 2016-09-12 15:53:54 -07:00 committed by Harshavardhana
parent 85e2d886bc
commit 895471afa1

View File

@ -37,8 +37,11 @@ type rateLimit struct {
// channel this is in-turn used to rate limit incoming connections in // channel this is in-turn used to rate limit incoming connections in
// ServeHTTP() http.Handler method. // ServeHTTP() http.Handler method.
func (c *rateLimit) acquire() error { func (c *rateLimit) acquire() error {
//lock access to enter waitQueue
c.lock.Lock()
// Kick out clients when it is really crowded // Kick out clients when it is really crowded
if len(c.waitQueue) == cap(c.waitQueue) { if len(c.waitQueue) == cap(c.waitQueue) {
defer c.lock.Unlock() //unlock after return
return errTooManyRequests return errTooManyRequests
} }
@ -46,11 +49,15 @@ func (c *rateLimit) acquire() error {
// wanting to process their requests // wanting to process their requests
c.waitQueue <- struct{}{} c.waitQueue <- struct{}{}
// Moving from wait to work queue is protected by a mutex // Unlock now. If we unlock before sending to the waitQueue
// to avoid draining waitQueue with multiple simultaneous clients. // channel, we can have multiple go-routines blocked on
c.lock.Lock() // sending to the waitQueue (and exceeding the max. number of
c.workQueue <- <-c.waitQueue // waiting connections.)
c.lock.Unlock() c.lock.Unlock()
// Block to put a waiting go-routine into processing mode.
c.workQueue <- <-c.waitQueue
return nil return nil
} }