the static threaded web server can now be configured for the number of threads to open
Costa Tsaousis (ktsaou) committed
Jan 8, 2018 at 00:37 UTC
3889305d12ad56a33e2a9a90e16f9886bfb0817b
4 files changed
+93
-26
src/main.c
+1
-1
@@ -76,7 +76,7 @@ struct netdata_static_thread static_threads[] = {
76
{"PLUGINSD", NULL, NULL, 1, NULL, NULL, pluginsd_main},
77
{"WEB_SERVER[multi]", NULL, NULL, 1, NULL, NULL, socket_listen_main_multi_threaded},
78
{"WEB_SERVER[single]", NULL, NULL, 0, NULL, NULL, socket_listen_main_single_threaded},
79
- {"WEB_SERVER[static]", NULL, NULL, 0, NULL, NULL, socket_listen_main_static_threaded},
79
+ {"WEB_SERVER[static1]", NULL, NULL, 0, NULL, NULL, socket_listen_main_static_threaded},
80
{"STREAM", NULL, NULL, 0, NULL, NULL, rrdpush_sender_thread},
81
{"STATSD", NULL, NULL, 1, NULL, NULL, statsd_main},
82
src/socket.c
+2
-2
@@ -1080,7 +1080,7 @@ static inline void poll_close_fd(struct poll *p, struct pollinfo *pi) {
1080
pi->del_callback(pf->fd, pi->socktype, pi->data);
1081
}
1082
1083
- info("POLLFD: closing fd %d", pf->fd);
1083
+ // info("POLLFD: closing fd %d", pf->fd);
1084
close(pf->fd);
1085
pf->fd = -1;
1086
pf->events = 0;
@@ -1282,7 +1282,7 @@ void poll_events(LISTEN_SOCKETS *sockets
1282
}
1283
else {
1284
// accept ok
1285
- info("POLLFD: LISTENER: client '[%s]:%s' connected to '%s' on fd %d", client_ip, client_port, sockets->fds_names[i], nfd);
1285
+ // info("POLLFD: LISTENER: client '[%s]:%s' connected to '%s' on fd %d", client_ip, client_port, sockets->fds_names[i], nfd);
1286
poll_add_fd(&p, nfd, SOCK_STREAM, POLLIN, POLLINFO_FLAG_CLIENT_SOCKET, client_ip, client_port);
1287
1288
// it may have reallocated them, so refresh our pointers
src/web_client.c
+9
-9
@@ -120,10 +120,6 @@ struct web_client *web_client_create_on_fd(int fd, const char *client_ip, const
120
w->origin[0] = '*';
121
web_client_enable_wait_receive(w);
122
123
- if(web_clients) web_clients->prev = w;
124
- w->next = web_clients;
125
- web_clients = w;
126
-
123
web_client_connected();
124
return(w);
125
}
@@ -305,15 +301,19 @@ void web_client_reset(struct web_client *w) {
301
}
302
303
struct web_client *web_client_free(struct web_client *w) {
304
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Closing web client from %s port %s.", w->id, w->client_ip, w->client_port);
305
+
306
web_client_reset(w);
307
310
- struct web_client *n = w->next;
311
- if(w == web_clients) web_clients = n;
308
+ struct web_client *n = NULL;
309
+ if(web_server_mode != WEB_SERVER_MODE_STATIC_THREADED) {
310
+ struct web_client *n = w->next;
311
+ if (w == web_clients) web_clients = n;
312
313
- debug(D_WEB_CLIENT_ACCESS, "%llu: Closing web client from %s port %s.", w->id, w->client_ip, w->client_port);
313
+ if(w->prev) w->prev->next = w->next;
314
+ if(w->next) w->next->prev = w->prev;
315
+ }
316
315
- if(w->prev) w->prev->next = w->next;
316
- if(w->next) w->next->prev = w->prev;
317
buffer_free(w->response.header_output);
318
buffer_free(w->response.header);
319
buffer_free(w->response.data);
src/web_server.c
+81
-14
@@ -20,8 +20,11 @@ static void log_allocations(void)
20
mi = mallinfo();
21
if(mi.uordblks > used) {
22
int clients = 0;
23
- struct web_client *w;
24
- for(w = web_clients; w ; w = w->next) clients++;
23
+
24
+ if(web_server_mode != WEB_SERVER_MODE_STATIC_THREADED) {
25
+ struct web_client *w;
26
+ for (w = web_clients; w; w = w->next) clients++;
27
+ }
28
29
info("Allocated memory: used %d KB (+%d B), mmap %d KB (+%d B), heap %d KB (+%d B). %d web clients connected.",
30
mi.uordblks / 1024,
@@ -402,11 +405,18 @@ void *socket_listen_main_single_threaded(void *ptr) {
405
// --------------------------------------------------------------------------------------
406
// the main socket listener - STATIC-THREADED
407
408
+static __thread size_t web_server_static_connected = 0,
409
+ web_server_static_disconnected = 0,
410
+ web_server_static_receptions = 0,
411
+ web_server_static_sends = 0;
412
+
413
// new TCP client connected
414
static void *web_server_add_callback(int fd, int socktype, short int *events, const char *client_ip, const char *client_port) {
415
(void)fd;
416
(void)socktype;
417
418
+ web_server_static_connected++;
419
+
420
*events = POLLIN;
421
422
debug(D_WEB_CLIENT_ACCESS, "LISTENER on %d: new connection.", fd);
@@ -425,6 +435,8 @@ static void web_server_del_callback(int fd, int socktype, void *data) {
435
(void)fd;
436
(void)socktype;
437
438
+ web_server_static_disconnected++;
439
+
440
struct web_client *w = (struct web_client *)data;
441
442
if(likely(w)) {
@@ -452,6 +464,8 @@ static int web_server_rcv_callback(int fd, int socktype, void *data, short int *
464
(void)fd;
465
(void)socktype;
466
467
+ web_server_static_receptions++;
468
+
469
struct web_client *w = (struct web_client *)data;
470
471
if(unlikely(!web_client_has_wait_receive(w)))
@@ -489,6 +503,8 @@ static int web_server_snd_callback(int fd, int socktype, void *data, short int *
503
(void)fd;
504
(void)socktype;
505
506
+ web_server_static_sends++;
507
+
508
struct web_client *w = (struct web_client *)data;
509
510
if(unlikely(!web_client_has_wait_send(w)))
@@ -506,31 +522,82 @@ static int web_server_snd_callback(int fd, int socktype, void *data, short int *
522
return web_server_check_client_status(w);
523
}
524
525
+static void socket_listen_main_static_threaded_worker_cleanup(void *ptr) {
526
+ (void)ptr;
527
+
528
+ info("stopped after %zu connects, %zu disconnects, %zu receptions and %zu sends",
529
+ web_server_static_connected,
530
+ web_server_static_disconnected,
531
+ web_server_static_receptions,
532
+ web_server_static_sends
533
+ );
534
+}
535
+
536
+void *socket_listen_main_static_threaded_worker(void *ptr) {
537
+ (void)ptr;
538
+
539
+ netdata_thread_cleanup_push(socket_listen_main_static_threaded_worker_cleanup, ptr);
540
+
541
+ poll_events(&api_sockets
542
+ , web_server_add_callback
543
+ , web_server_del_callback
544
+ , web_server_rcv_callback
545
+ , web_server_snd_callback
546
+ , web_allow_connections_from
547
+ , NULL
548
+ );
549
+
550
+ netdata_thread_cleanup_pop(1);
551
+ return NULL;
552
+}
553
+
554
+static long long static_threaded_threads_count = 1;
555
+static netdata_thread_t *static_threaded_threads_ids = NULL;
556
+
557
static void socket_listen_main_static_threaded_cleanup(void *ptr) {
558
struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
559
if(static_thread->enabled) {
560
static_thread->enabled = 0;
561
514
- info("%s: cleaning up...", netdata_thread_tag());
562
+ int i;
563
+ for(i = 1; i < static_threaded_threads_count; i++) {
564
+ info("stopping worker %d", i+1);
565
+ netdata_thread_cancel(static_threaded_threads_ids[i]);
566
+ }
567
+
568
+ info("cleaning up...");
569
listen_sockets_close(&api_sockets);
570
}
571
}
572
573
void *socket_listen_main_static_threaded(void *ptr) {
574
netdata_thread_cleanup_push(socket_listen_main_static_threaded_cleanup, ptr);
521
- web_server_mode = WEB_SERVER_MODE_STATIC_THREADED;
575
+ web_server_mode = WEB_SERVER_MODE_STATIC_THREADED;
576
523
- if(!api_sockets.opened)
524
- fatal("LISTENER: no listen sockets available.");
577
+ if(!api_sockets.opened)
578
+ fatal("LISTENER: no listen sockets available.");
579
526
- poll_events(&api_sockets
527
- , web_server_add_callback
528
- , web_server_del_callback
529
- , web_server_rcv_callback
530
- , web_server_snd_callback
531
- , web_allow_connections_from
532
- , NULL
533
- );
580
+ // 6 threads is the optimal value
581
+ // since 6 are the parallel connections browsers will do
582
+ // so, if the machine has more CPUs, avoid using resources unnecessarily
583
+ int def_thread_count = (processors > 6)?6:processors;
584
+
585
+ static_threaded_threads_count = config_get_number(CONFIG_SECTION_WEB, "web server threads", def_thread_count);
586
+ if(static_threaded_threads_count < 1) static_threaded_threads_count = 1;
587
+
588
+ static_threaded_threads_ids = callocz((size_t)static_threaded_threads_count, sizeof(netdata_thread_t));
589
+
590
+ int i;
591
+ for(i = 1; i < static_threaded_threads_count; i++) {
592
+ char tag[50 + 1];
593
+ snprintfz(tag, 50, "WEB_SERVER[static%d]", i+1);
594
+
595
+ info("starting worker %d", i+1);
596
+ netdata_thread_create(&static_threaded_threads_ids[i], tag, NETDATA_THREAD_OPTION_DEFAULT, socket_listen_main_static_threaded_worker, NULL);
597
+ }
598
+
599
+ // and the main one
600
+ socket_listen_main_static_threaded_worker(NULL);
601
602
netdata_thread_cleanup_pop(1);
603
return NULL;