[plt-scheme] Limiting Concurrent Connections to Web Server

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Fri Jan 16 11:25:30 EST 2009

Thanks for the catch Matthew. I've done the asynchronous reply technique.

I've also added an 'over-limit' keyword. It has three options: 'block,
'kill-new, and 'kill-old. From the new documentation:

If there are no additional spaces inside the limit and a new request
is received, the over-limit option determines what is done. The
default ('block) causes the new request to block until an old request
is finished handling. If over-limit is 'kill-new, then the new request
handler is killed – a form of load-shedding. If over-limit is
'kill-old, then the oldest request handler is killed – prioritizing
new connections over old. (This setting is a little dangerous because
requests might never finish if there is constant load.)


On Fri, Jan 16, 2009 at 9:03 AM, Matthew Flatt <mflatt at cs.utah.edu> wrote:
> At Fri, 16 Jan 2009 08:33:29 -0700, Jay McCarthy wrote:
>>  (if (< i num)
>>                    (wrap-evt in-ch
>>                              (lambda (req)
>>                                (channel-put (in-req-reply-ch req) #t)
>>                                (loop (add1 i)
>>                                      (list* (in-req-partner req) partners))))
>>                    never-evt)
> A detail that I didn't catch before: if the process that sends the
> request terminates just before the `channel-put', then the lock server
> can get get stuck trying to send a reply to a thread that isn't there
> anymore.
> The simplest solution is to send the reply asynchronously:
>  (wrap-evt in-ch
>           (lambda (req)
>             (thread (lambda ()
>                       (channel-put (in-req-reply-ch req) #t)))
>             (loop (add1 i)
>                   (list* (in-req-partner req) partners))))
> Another solution is to sync on a combination of the thread and a
> channel-put evt:
>  (lambda (req)
>   (sync
>    (handle-evt (channel-put-evt (in-req-reply-ch req) #t)
>       (lambda ()
>         ;; notification accepted
>         (loop (add1 i)
>               (list* (in-req-partner req) partners))))
>     (handle-evt (in-req-partner req)
>        (lambda ()
>          ;; other thread died first
>          (loop i partners)))))
> Since your lock server already cleans up for partners that disappear,
> though, the asynchronous reply is probably better.
> If a thread can get suspended, and if you're using the latter solution,
> then you'd want to go even further, and have the reply lifted up to the
> main `sync' (because a suspended thread doesn't receive on a channel
> but also isn't dead). I don't think that case applies in the web
> server, though --- and the asynchronous reply covers that case, too.

Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University

"The glory of God is Intelligence" - D&C 93

Posted on the users mailing list.