commit - 2f713fe5ea69a546ed14839ae0212754176d2524
commit + ea7963b95027594a330a01f1770fba059750944c
blob - ab3d68e47d567bc3609e5683e585a5895b3ea6ac
blob + 33b68401e2c5f82f89fb4c5f505fd851596b8e66
--- gotwebd/gotwebd.c
+++ gotwebd/gotwebd.c
www_username = env->www_user;
}
+ if (proc_type == GOTWEBD_PROC_SERVER) {
+ env->worker_load = calloc(env->prefork,
+ sizeof(env->worker_load[0]));
+ if (env->worker_load == NULL)
+ fatal("calloc");
+ }
+
pw = getpwnam(www_username);
if (pw == NULL)
fatalx("unknown user %s", www_username);
blob - 0719d555453958214b9038725b19d44c068a5c05
blob + 02bc544637cc043a756a9a812d12548947cd9442
--- gotwebd/gotwebd.h
+++ gotwebd/gotwebd.h
struct event *resp_event;
int sock_id;
uint32_t request_id;
+ int worker_idx;
uint8_t *buf;
size_t buf_len;
uint16_t prefork;
int gotweb_pending;
int gotweb_cur;
+ int *worker_load;
int server_cnt;
blob - 1a5dfceec28e4ec209e93323844f9bb122707357
blob + 29572c09c6b9b12145cca001b433ff270b0378a7
--- gotwebd/sockets.c
+++ gotwebd/sockets.c
static void
cleanup_request(struct request *c)
{
+ struct gotwebd *env = gotwebd_env;
+
cgi_inflight--;
+
+ if (c->worker_idx != -1) {
+ if (env->worker_load[c->worker_idx] <= 0)
+ fatalx("request in flight on worker with zero load");
+ env->worker_load[c->worker_idx]--;
+ }
del_request(c);
env->gotweb_pending--;
}
+
+static struct imsgev *
+select_worker(struct request *c)
+{
+ struct gotwebd *env = gotwebd_env;
+ int i, least_busy_worker_idx, min_load;
+ min_load = env->worker_load[0];
+ least_busy_worker_idx = 0;
+ for (i = 1; i < env->prefork; i++) {
+ if (env->worker_load[i] > min_load)
+ continue;
+
+ min_load = env->worker_load[i];
+ least_busy_worker_idx = i;
+ }
+
+ log_debug("dispatching request %u to gotweb %d",
+ c->request_id, least_busy_worker_idx);
+
+ c->worker_idx = least_busy_worker_idx;
+ return &env->iev_gotweb[least_busy_worker_idx];
+}
+
static int
process_request(struct request *c)
{
ic.priv_fd[i] = -1;
ic.fd = -1;
- /* Round-robin requests across gotweb processes. */
- iev_gotweb = &env->iev_gotweb[env->gotweb_cur];
- env->gotweb_cur = (env->gotweb_cur + 1) % env->prefork;
-
+ iev_gotweb = select_worker(c);
ret = imsg_compose_event(iev_gotweb, GOTWEBD_IMSG_REQ_PROCESS,
GOTWEBD_PROC_SERVER, -1, c->fd, &ic, sizeof(ic));
if (ret == -1) {
log_warn("imsg_compose_event");
+ c->worker_idx = -1;
return -1;
}
c->fd = -1;
c->client_status = CLIENT_REQUEST;
+ env->worker_load[c->worker_idx]++;
return 0;
}
for (i = 0; i < gotwebd_env->prefork; i++)
imsgbuf_clear(&gotwebd_env->iev_gotweb[i].ibuf);
free(gotwebd_env->iev_gotweb);
-
+ free(gotwebd_env->worker_load);
free(gotwebd_env);
exit(0);
c->buf_len = 0;
c->client_status = CLIENT_CONNECT;
c->request_id = get_request_id();
+ c->worker_idx = -1;
event_set(&c->ev, s, EV_READ, read_fcgi_records, c);
event_add(&c->ev, NULL);