--- fcgid_bridge.c.1725557 2016-01-19 17:13:02.316683000 +0100 +++ fcgid_bridge.c 2017-09-07 11:54:52.474053000 +0200 @@ -30,8 +30,30 @@ #include "fcgid_spawn_ctl.h" #include "fcgid_protocol.h" #include "fcgid_bucket.h" -#define FCGID_APPLY_TRY_COUNT 2 -#define FCGID_REQUEST_COUNT 32 +/* FCGID_REQUEST_COUNT: + * how many times to attempt a spawn request */ +#define FCGID_REQUEST_COUNT 8 +/* FCGID_REQUEST_INITIAL_STEP: + * The initial iterations of the inner loop */ +#define FCGID_REQUEST_INITIAL_STEP 2 +/* FCGID_REQUEST_INITIAL_SLEEP: + * The initial sleep time in ms of the inner loop */ +#define FCGID_REQUEST_INITIAL_SLEEP 50 +/* FCGID_REQUEST_STEPSIZE: + * every FCGID_REQUEST_COUNT loop, increase the inner loop by this size */ +#define FCGID_REQUEST_STEPSIZE 6 +/* FCGID_REQUEST_SLEEPSIZE: + * every FCGID_REQUEST_COUNT loop, increase the inner loop sleeptime + * by FCGID_REQUEST_SLEEPSIZE miliseconds */ +#define FCGID_REQUEST_SLEEPSIZE 150 +/* FCGID_REQUEST_STEPCOUNT: + * how many FCGID_REQUEST_COUNT loop iterations to increase the + * inner loop by FCGID_REQUEST_STEPSIZE */ +#define FCGID_REQUEST_STEPCOUNT 4 +/* FCGID_REQUEST_SLEEPCOUNT: + * how many FCGID_REQUEST_COUNT loop iterations to increase the + * inner loop by FCGID_REQUEST_SLEEPSIZE msec */ +#define FCGID_REQUEST_SLEEPCOUNT 4 #define FCGID_BRIGADE_CLEAN_STEP 32 static fcgid_procnode *apply_free_procnode(request_rec *r, @@ -425,7 +447,7 @@ { fcgid_command fcgi_request; fcgid_bucket_ctx *bucket_ctx; - int i, j, cond_status; + int i, j, cond_status, wait_msec, try_spawn; const char *location = NULL; bucket_ctx = apr_pcalloc(r->pool, sizeof(*bucket_ctx)); @@ -434,34 +456,40 @@ apr_pool_cleanup_register(r->pool, bucket_ctx, bucket_ctx_cleanup, apr_pool_cleanup_null); procmgr_init_spawn_cmd(&fcgi_request, r, cmd_conf); - + bucket_ctx->ipc.connect_timeout = + fcgi_request.cmdopts.ipc_connect_timeout; + bucket_ctx->ipc.communation_timeout = + fcgi_request.cmdopts.ipc_comm_timeout; + + /* our initial wait time is short */ + wait_msec = FCGID_REQUEST_INITIAL_SLEEP; + /* initially we try to spawn a processes after failing to apply 2 times */ + try_spawn = FCGID_REQUEST_INITIAL_STEP; /* 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++) { - bucket_ctx->ipc.connect_timeout = - fcgi_request.cmdopts.ipc_connect_timeout; - bucket_ctx->ipc.communation_timeout = - fcgi_request.cmdopts.ipc_comm_timeout; + for (j = 0; j < try_spawn; j++) { /* 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)); + /* We couldn't get a free process slot, if it was the very + first try, lets check if any were spawned at all */ + if (i == 0 && j == 0 + && count_busy_processes(r, &fcgi_request)==0) { + /* there are no processes so try to spawn one */ + procmgr_send_spawn_cmd(&fcgi_request, r); 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_send_spawn_cmd(&fcgi_request, r); + /* now wait a bit for a process to free up */ + apr_sleep(apr_time_from_msec(wait_msec)); + } /* Connect to the fastcgi server */ @@ -476,6 +504,40 @@ else break; } + + /* It seems to be busy, every iteration we try to spawn less + * often as its more and more likely we hit the max processes + * limit. Also sleep longer so we don't waste too much cycles. + * When nearing the end of our retry lifitime, decrease sleep + * time again so we still have a chance at getting a process. */ + /* loop iterations: + 0) 2 x 50ms = 100ms + 1) 8 x 200ms = 1600ms + 2) 14 x 350ms = 4900ms + 3) 20 x 500ms = 10000ms + 4) 26 x 650ms = 16900ms + 5) 26 x 500ms = 13000ms + 6) 26 x 350ms = 9100ms + 7) 26 x 200ms = 5200ms + -------- + + 60800ms (8x spawn, 148 apply) + Old: 64000ms (64x spawn, 128 apply) + */ + if(i < FCGID_REQUEST_STEPCOUNT){ + try_spawn+=FCGID_REQUEST_STEPSIZE; + } + if(i < FCGID_REQUEST_SLEEPCOUNT){ + wait_msec+=FCGID_REQUEST_SLEEPSIZE; + }else{ + /* our request count exceeds the FCGID_REQUEST_SLEEPCOUNT + * value, so lets give it more priority by lowering the wait + * and hopefulle preventing a HTTP_SERVICE_UNAVAILABLE */ + wait_msec-=FCGID_REQUEST_SLEEPSIZE; + } + + /* we tried try_spawn times to get a process slot but we + * failed. So now try to spawn a new one. */ + procmgr_send_spawn_cmd(&fcgi_request, r); } /* Now I get a connected ipc handle */