You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Lazy <la...@gmail.com> on 2011/12/29 13:04:59 UTC

long timeout on overloaded mod_fcgid

Hi,

When some vhost's scripts exhaust all process slots available to it
(FcgidMaxProcessesPerClass),
next requests are waiting for over 60 seconds before issuing 503 error.

I came across this while modifying suexec to use cgroups to provide
better resource separation for use in our shared hosting environment.
When some vhost got it's cpu resources sharply reduced its incoming
traffic quickly occupyed all available connection slots rendering
whole web server unavailable.

This could lead to a dos situation when unresponsive fcgi application
will occupy large number of connection slots.

mod_fcgid could use process statistics to detect these situations and
return 503 error sooner.

Maybe check for active and idle time, or allow only a limited number
of clients to wait for a single fcgi process class if all of them are
busy.

http://svn.apache.org/repos/asf/httpd/mod_fcgid/trunk/modules/fcgid/fcgid_bridge.c

#define FCGID_REQUEST_COUNT 32
#define FCGID_APPLY_TRY_COUNT 2

handle_request(request_rec * r, int role, fcgid_cmd_conf *cmd_conf,
               apr_bucket_brigade * output_brigade)
{
...
    /* Try to get a connected ipc handle */
    for (i = 0; i < FCGID_REQUEST_COUNT; i++) {
        /* Apply a free process slot, send a spawn request if I can't get one */
        for (j = 0; j < FCGID_APPLY_TRY_COUNT; j++) {
            /* Init spawn request */
            procmgr_init_spawn_cmd(&fcgi_request, r, cmd_conf);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
do we have to do it on every iteration ?

if yes I think it can be moved just before
            procmgr_post_spawn_cmd(&fcgi_request, r);
so if there is a free procnode we don't call procmgr_init_spawn_cmd at all


            bucket_ctx->ipc.connect_timeout =
                fcgi_request.cmdopts.ipc_connect_timeout;
            bucket_ctx->ipc.communation_timeout =
                fcgi_request.cmdopts.ipc_comm_timeout;

            /* Apply a process slot */
            bucket_ctx->procnode = apply_free_procnode(r, &fcgi_request);
            if (bucket_ctx->procnode)
                break;

            /* Avoid sleeping the very first time through if there are no
               busy processes; the problem is just that we haven't spawned
               anything yet, so waiting is pointless */
            if (i > 0 || j > 0 || count_busy_processes(r, &fcgi_request)) {
                apr_sleep(apr_time_from_sec(1));

                bucket_ctx->procnode = apply_free_procnode(r, &fcgi_request);
                if (bucket_ctx->procnode)
                    break;
            }

            /* Send a spawn request if I can't get a process slot */
            procmgr_post_spawn_cmd(&fcgi_request, r);
        }


-- 
Michal Grzedzicki