Welcome! Log In Create A New Profile

Advanced

[PATCH] Events: fixed balancing between workers with EPOLLEXCLUSIVE

Maxim Dounin
December 24, 2021 05:16PM
# HG changeset patch
# User Maxim Dounin <mdounin@mdounin.ru>
# Date 1640383910 -10800
# Sat Dec 25 01:11:50 2021 +0300
# Node ID 4fa260f60bac03037017a33672da1ac75ac31408
# Parent d07456044b611848abe244d65b585159037f8980
Events: fixed balancing between workers with EPOLLEXCLUSIVE.

Linux with EPOLLEXCLUSIVE usually notifies only the process which was first
to add the listening socket to the epoll instance. As a result most of the
connections are handled by the first worker process (ticket #2285). To fix
this, we re-add the socket periodically, so other workers will get a chance
to accept connections.

diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -55,6 +55,7 @@ ngx_uint_t ngx_accept_events;
ngx_uint_t ngx_accept_mutex_held;
ngx_msec_t ngx_accept_mutex_delay;
ngx_int_t ngx_accept_disabled;
+ngx_uint_t ngx_use_exclusive_accept;


#if (NGX_STAT_STUB)
@@ -644,6 +645,8 @@ ngx_event_process_init(ngx_cycle_t *cycl

#endif

+ ngx_use_exclusive_accept = 0;
+
ngx_queue_init(&ngx_posted_accept_events);
ngx_queue_init(&ngx_posted_next_events);
ngx_queue_init(&ngx_posted_events);
@@ -889,6 +892,8 @@ ngx_event_process_init(ngx_cycle_t *cycl
if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
&& ccf->worker_processes > 1)
{
+ ngx_use_exclusive_accept = 1;
+
if (ngx_add_event(rev, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT)
== NGX_ERROR)
{
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -466,6 +466,7 @@ extern ngx_uint_t ngx_accept
extern ngx_uint_t ngx_accept_mutex_held;
extern ngx_msec_t ngx_accept_mutex_delay;
extern ngx_int_t ngx_accept_disabled;
+extern ngx_uint_t ngx_use_exclusive_accept;


#if (NGX_STAT_STUB)
diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -11,6 +11,9 @@


static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all);
+#if (NGX_HAVE_EPOLLEXCLUSIVE)
+static void ngx_reorder_accept_events(ngx_listening_t *ls);
+#endif
static void ngx_close_accepted_connection(ngx_connection_t *c);


@@ -314,6 +317,10 @@ ngx_event_accept(ngx_event_t *ev)
}

} while (ev->available);
+
+#if (NGX_HAVE_EPOLLEXCLUSIVE)
+ ngx_reorder_accept_events(ls);
+#endif
}


@@ -420,6 +427,55 @@ ngx_disable_accept_events(ngx_cycle_t *c
}


+#if (NGX_HAVE_EPOLLEXCLUSIVE)
+
+static void
+ngx_reorder_accept_events(ngx_listening_t *ls)
+{
+ ngx_connection_t *c;
+
+ /*
+ * Linux with EPOLLEXCLUSIVE usually notifies only the process which
+ * was first to add the listening socket to the epoll instance. As
+ * a result most of the connections are handled by the first worker
+ * process. To fix this, we re-add the socket periodically, so other
+ * workers will get a chance to accept connections.
+ */
+
+ if (!ngx_use_exclusive_accept) {
+ return;
+ }
+
+#if (NGX_HAVE_REUSEPORT)
+
+ if (ls->reuseport) {
+ return;
+ }
+
+#endif
+
+ c = ls->connection;
+
+ if (c->requests++ % 16 != 0) {
+ return;
+ }
+
+ if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT)
+ == NGX_ERROR)
+ {
+ return;
+ }
+
+ if (ngx_add_event(c->read, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT)
+ == NGX_ERROR)
+ {
+ return;
+ }
+}
+
+#endif
+
+
static void
ngx_close_accepted_connection(ngx_connection_t *c)
{

_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[PATCH] Events: fixed balancing between workers with EPOLLEXCLUSIVE

Maxim Dounin 187 December 24, 2021 05:16PM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 81
Record Number of Users: 6 on February 13, 2018
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready